M2tklib not updating U32NUMFN element

hi all,

I'm using the m2tklib library (excellent library... :slight_smile: ) to build a menu that will display temperature readouts from a sensor. In the main program, the U8NUM element wasnt updating automatically. I tried a U8NUMFN and still no automatic updates. So i started a new sketch to try and figure out whats going on.

The sketch is:

#include "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"

//U8GLIB(             d0, d1, d2, d3, d4, d5, d6, d7, en, cs1, cs2, di, rw, reset) 
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 37,  33,  34, 36, 35, 30);

uint32_t global_value = 0;

uint32_t u32_cb(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
  if ( msg == M2_U32_MSG_GET_VALUE ){
    global_value ++;
    Serial.println(global_value);
  }
  return global_value;
}

M2_U32NUMFN(el_u32_cb, "r1c4", u32_cb);

// m2 object and constructor
M2tk m2(&el_u32_cb, m2_es_arduino_serial, m2_eh_4bs, m2_gh_u8g_bf);

void draw(void) {
    m2.draw();
}

void setup() {
  
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);
  m2.setFont(0, u8g_font_6x10 );
}

void loop() {
  m2.checkKey();
  if ( m2.handleKey() != 0 ) {
    u8g.firstPage();  
    do {
      m2.checkKey();
      draw();
    } while( u8g.nextPage() );
  }
  draw();
  delay(500);
}

The sketch compiles and loads ok. The value of the element is expected to increment but it just takes on the the initial value when it loads and thats it.

Any help would be very appreciated... :slight_smile:

Hi

  if ( msg == M2_U32_MSG_GET_VALUE ){
    global_value ++;
    Serial.println(global_value);
  }

This is not a correct usage of the u8glib picture loop: Do not modify global variables within the picture loop. This is tricky here, because this part of is called within m2.draw() which is called by draw() which is part of the picture loop.

  }
  draw();
  delay(500);

draw() is called outside of the picture loop. This will not work.

Alltogether i would suggest this code (not tested):

#include "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"

//U8GLIB(             d0, d1, d2, d3, d4, d5, d6, d7, en, cs1, cs2, di, rw, reset) 
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 37,  33,  34, 36, 35, 30);

uint32_t global_value = 0;

uint32_t u32_cb(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
  if ( msg == M2_U32_MSG_GET_VALUE ){
    // wrong place to increment, do this in loop()
    // global_value ++;
   //  Serial.println(global_value);
  }
  return global_value;
}

M2_U32NUMFN(el_u32_cb, "r1c4", u32_cb);

// m2 object and constructor
M2tk m2(&el_u32_cb, m2_es_arduino_serial, m2_eh_4bs, m2_gh_u8g_bf);

void draw(void) {
    m2.draw();
}

void setup() {
  
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);
  m2.setFont(0, u8g_font_6x10 );
}

void loop() {
  m2.checkKey();
  // introduce a new variable "update_required"
  if ( m2.handleKey() != 0 || update_required != 0 ) {
   update_required = 0;
    u8g.firstPage();  
    do {
      m2.checkKey();
      draw();
    } while( u8g.nextPage() );
  }
  // calling draw() is useless here, picture loop is missing
  // draw();
  delay(500);
   global_value ++;
   update_required = 1;   // force redraw by setting this variable to 1
   Serial.println(global_value);
}

Oliver

Hi Oliver,

Thank you for your prompt reply. Your suggestion did the trick. I'll keep you posted on progress :slight_smile:

Michael

Good to read, that this works for you.

Oliver

Hi Oliver,

I'm trying to do a couple of things that don't seem to be working:

  1. Im trying to setup an intro screen. I found two examples that are supposed to work - but they didnt make sense and didnt work in my case.

  2. is there an easy way to find which menu (root) is being used. Reason is that i want update_required = 0 when some menus are being used such as menus used to get an input. For example, an input variable might be constantly updated (such as a clock reading) but shouldn't get updated when the user is entering new values in the 'change time' menu.

The test code i'm using is attached:

#include "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"
#include "myimages.h"

//U8GLIB(             d0, d1, d2, d3, d4, d5, d6, d7, en, cs1, cs2, di, rw, reset)
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 37,  33,  34, 36, 35, 30);

uint32_t global_value_1 = 0;
uint32_t global_value_2 = 0;
uint32_t global_value_3 = 0;
uint8_t  update_required = 0;
uint8_t  timeout = 50;      // 60 seconds (approx)  

#define INTRO 0
#define MAIN_MENU 1
uint8_t state;

M2_EXTERN_ALIGN(el_m01);
M2_EXTERN_ALIGN(el_m02);
M2_EXTERN_ALIGN(el_m03);


uint32_t u32_cb_1(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
//  if ( msg == M2_U32_MSG_GET_VALUE ){
    // wrong place to increment, do this in loop()
    // global_value ++;
    // Serial.println(global_value);
//  }
  return global_value_1;
}

uint32_t u32_cb_2(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
//  if ( msg == M2_U32_MSG_GET_VALUE ){
//  }
  return global_value_2;
}

M2_LABEL(el_m00_label, "b0",  "-=    Main Menu    =-" );
M2_LABEL(el_underline, "b0",  "---------------------" );
M2_ROOT(el_m00_submenu1, "f0", "Menu 1", &el_m01 );
M2_ROOT(el_m00_submenu2, "f0", "Menu 2", &el_m02 );
M2_ROOT(el_m00_submenu3, "f0", "Menu 3", &el_m03 );
M2_LIST(el_m00_l1) = { &el_m00_label, &el_underline, &el_m00_submenu1, &el_m00_submenu2, &el_m00_submenu3 };
M2_VLIST(el_m00_vl, NULL, el_m00_l1);  
M2_ALIGN(el_m00, "-0|2W128H64", &el_m00_vl);

M2_U32NUMFN(el_u32_cb_1, "r1c4", u32_cb_1);
M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m01_ok, NULL, " ok ", fn_ok1);
M2_LIST(el_l1) = { &el_u32_cb_1, &el_space1, &el_space1, &el_m01_ok  };
M2_VLIST( el_v1, NULL,  el_l1);
M2_ALIGN(el_m01, "-0|2W128H64", &el_v1);

M2_U32NUMFN(el_u32_cb_2, "r1c4", u32_cb_2);
//M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m02_ok, NULL, " ok ", fn_ok2);
M2_LIST(el_l2) = { &el_u32_cb_2, &el_space1, &el_space1, &el_m02_ok  };
M2_VLIST( el_v2, NULL,  el_l2);
M2_ALIGN(el_m02, "-0|2W128H64", &el_v2);

M2_U32NUM(el_u32_cb_3, "r1c4", &global_value_3);
//M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m03_ok, NULL, " ok ", fn_ok3);
M2_LIST(el_l3) = { &el_u32_cb_3, &el_space1, &el_space1, &el_m03_ok  };
M2_VLIST( el_v3, NULL,  el_l3);
M2_ALIGN(el_m03, "-0|2W128H64", &el_v3);

// m2 object and constructor
M2tk m2(&el_m00, m2_es_arduino_serial, m2_eh_4bs, m2_gh_u8g_bf);

void fn_ok1(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 0);
}

void fn_ok2(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 1);
}

void fn_ok3(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 2);
}

void draw(void) {
    m2.draw();
}

void setup() {
 
  state = INTRO;
//  IntroScreen();
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);
  m2.setFont(0, u8g_font_6x10 );


}

void loop() {

  m2.checkKey();
  
  if ( m2.handleKey() != 0 ) {
    // key pressed
    timeout = 50;
  }
  
  // introduce a new variable "update_required"
  if ( m2.handleKey() != 0 || update_required != 0 ) {
    update_required = 0;
    u8g.firstPage(); 
    do {
      m2.checkKey();
      draw();
    } while( u8g.nextPage() );
  }

  // calling draw() is useless here, picture loop is missing
  // draw();
  delay(100);

  timeout--;
  if ( timeout == 0 ) {
    // change to home menu...
    m2.setRoot(&el_m00);
  }

  global_value_1 ++;
  global_value_2 += 2;
  global_value_3 = global_value_1;
  // force redraw by setting this variable to 1
  update_required = 1;
  //  Serial.println(global_value);
  
  //SetNextState();
}

void SetNextState(void) {
  switch (state) {
    case INTRO:
      break;
    case MAIN_MENU:
      break;
  }
}


//Intro screen
void IntroScreen() {   

    u8g.firstPage();  

    do {
      u8g.drawXBM( 0, 0, 128, 64, image);
      draw();
    } while( u8g.nextPage() );

  delay(1000);
//  state = MAIN_MENU;
  
}

Any help is appreciated... :slight_smile:

Michael

To start with the second part of your question: Have a look at Google Code Archive - Long-term storage for Google Code Project Hosting.. This is probably the function you are looking for.

The first part of you question is partly discussed in tutorial 6: Google Code Archive - Long-term storage for Google Code Project Hosting..

For the splash screen i suggest this: Assign the null element (Google Code Archive - Long-term storage for Google Code Project Hosting.) to the constructor. After splash screen display time has been expired, set the menu root to your toplevel menu. To show your splash screen, simply check for the null element in the draw procedure:

void draw(void) {
  if ( m2.getRoot() == &m2_null_element ) {
      // draw splash screen
     ...
  }
  else {
     m2.draw();
  }
}

Oliver

Oliver,

Thanks... worked like a charm...

#include "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"
#include "images.h"

//U8GLIB(             d0, d1, d2, d3, d4, d5, d6, d7, en, cs1, cs2, di, rw, reset)
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 37,  33,  34, 36, 35, 30);


uint32_t global_value_1 = 0;
uint32_t global_value_2 = 0;
uint32_t global_value_3 = 0;
uint8_t  update_required = 0;
uint8_t  timeout = 50;      // 60 seconds (approx)  

M2_EXTERN_ALIGN(el_m01);
M2_EXTERN_ALIGN(el_m02);
M2_EXTERN_ALIGN(el_m03);


uint32_t u32_cb_1(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
//  if ( msg == M2_U32_MSG_GET_VALUE ){
    // wrong place to increment, do this in loop()
    // global_value ++;
    // Serial.println(global_value);
//  }
  return global_value_1;
}

uint32_t u32_cb_2(m2_rom_void_p el_u32_cb, uint8_t msg, uint32_t val)
{
//  if ( msg == M2_U32_MSG_GET_VALUE ){
//  }
  return global_value_2;
}

M2_LABEL(el_m00_label, "b0",  "-=    Main Menu    =-" );
M2_LABEL(el_underline, "b0",  "---------------------" );
M2_ROOT(el_m00_submenu1, "f0", "Menu 1", &el_m01 );
M2_ROOT(el_m00_submenu2, "f0", "Menu 2", &el_m02 );
M2_ROOT(el_m00_submenu3, "f0", "Menu 3", &el_m03 );
M2_LIST(el_m00_l1) = { &el_m00_label, &el_underline, &el_m00_submenu1, &el_m00_submenu2, &el_m00_submenu3 };
M2_VLIST(el_m00_vl, NULL, el_m00_l1);  
M2_ALIGN(el_m00, "-0|2W128H64", &el_m00_vl);

M2_U32NUMFN(el_u32_cb_1, "r1c4", u32_cb_1);
M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m01_ok, NULL, " ok ", fn_ok1);
M2_LIST(el_l1) = { &el_u32_cb_1, &el_space1, &el_space1, &el_m01_ok  };
M2_VLIST( el_v1, NULL,  el_l1);
M2_ALIGN(el_m01, "-0|2W128H64", &el_v1);

M2_U32NUMFN(el_u32_cb_2, "r1c4", u32_cb_2);
//M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m02_ok, NULL, " ok ", fn_ok2);
M2_LIST(el_l2) = { &el_u32_cb_2, &el_space1, &el_space1, &el_m02_ok  };
M2_VLIST( el_v2, NULL,  el_l2);
M2_ALIGN(el_m02, "-0|2W128H64", &el_v2);

M2_U32NUM(el_u32_cb_3, "r1c4", &global_value_3);
//M2_LABEL(el_space1, "b1", " ");
M2_BUTTON(el_m03_ok, NULL, " ok ", fn_ok3);
M2_LIST(el_l3) = { &el_u32_cb_3, &el_space1, &el_space1, &el_m03_ok  };
M2_VLIST( el_v3, NULL,  el_l3);
M2_ALIGN(el_m03, "-0|2W128H64", &el_v3);

// m2 object and constructor
//M2tk m2(&el_m00, m2_es_arduino_serial, m2_eh_4bs, m2_gh_u8g_bf);
M2tk m2(&m2_null_element, m2_es_arduino_serial, m2_eh_4bs, m2_gh_u8g_bf);


void fn_ok1(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 0);
}

void fn_ok2(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 1);
}

void fn_ok3(m2_el_fnarg_p fnarg) {
  m2.setRoot(&el_m00, 2);
}

void draw(void) {
  if ( m2.getRoot() == &m2_null_element ) {
    // draw splash screen
    u8g.drawXBM( 0, 0, 128, 64, myimage);
  }
  else {
    // draw the menu...
    m2.draw();
  }
}

void setup() {
 
  Serial.println("Setup1");
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);
  m2.setFont(0, u8g_font_6x10 );
  Serial.println("Setup2");

}

void loop() {

  Serial.println("Loop");
  m2.checkKey();
  
  if ( m2.handleKey() != 0 ) {
    // key pressed so reset the 'timer'
    timeout = 50;
    Serial.println("reset timer...");
  }
  
  // introduce a new variable "update_required"
  if ( m2.handleKey() != 0 || update_required != 0 ) {
    update_required = 0;
    u8g.firstPage(); 
    do {
      m2.checkKey();
      draw();
    } while( u8g.nextPage() );
  }

  delay(100);

  timeout--;
  if ( timeout == 0 ) {
    // change to home menu...
    m2.setRoot(&el_m00);
  }

  global_value_1 ++;
  global_value_2 += 2;
  global_value_3 = global_value_1;

  if ( m2.getRoot() == &el_m03 ) {
    // no updates...
    updating_time = 1;
    update_required = 0;
  }
  else {
    // force redraw 
    update_required = 1;
  }
  
}

Michael