Analog Joystick with M2TKLIB

I have a PS2 style thumb sticks I got from SparkFun (Thumb Joystick - COM-09032 - SparkFun Electronics), and I want to use it to navigate a menu on an LCD. After some googleing I found M2TKLIB, and it seems really cool, well thought out, and easy to enhance/extend. In fact, in no time, I extended the a library to support the analog inputs. My question is what keys should I map them to? I have 5 total (left, right, up, down, and push). I'm still learning this library, so I'm not really sure what are the most appropriate navigation keys. Currently I have them mapped to NEXT, PREV, DATA UP, DATA DOWN, and SELECT. And I'm using the 6 button event handler even though I only have 5 virtual buttons. Thoughts? Basic nav and data stuff seems to work ok, but I haven't really started creating my menu for my app yet. So far I have just played with the example apps. I am using a 2 line LCD so some of the examples seem to act strange. I suspect I didn't modify everything correctly to make the examples work appropriately on a 2 line display.

Oh, and by the way, the M2TKLIB library seems to work fine just dropping in the Adifrut LiquidCrystal library that works with there I2C LCD Backpack (i2c / SPI character LCD backpack - STEMMA QT / Qwiic : ID 292 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits).

Thanks!
Chad

Hi

I think the use of NEXT, PREV, DATA UP, DATA DOWN, and SELECT is already the best you can do.

I am using a 2 line LCD so some of the examples seem to act strange.

Maybe you can give more specific examples/code here. For example the format option "a" changes the behavior and indeed a0 might appear to be "strange".

Oliver

Thanks for the response! Totally love the library!

The DataEntry example project is one that was confusing for me. I changed the lcd(16,4) to lcd(16,2) because I only have 2 lines on my display. I didn't change any of the formats. I also changed the deceleration of m2 to this:

M2tk m2(&el_de_menu, m2_es_arduino_analog_joystick, m2_eh_6bs, m2_gh_lc);

And connected up the 5 keys I mentioned.

Chad

I think that the GRIDLIST doesn't work with 2 lines. Or it doesn't work with more rows than display lines in general. When I comment out rows in the list to just 2, it works great.

Another question. I'm using the 6bs event handler, so when editing data, the select button increments the data. the same action as DATA_UP. Because I don't have an EXIT key, would it make sense to make SELECT call nav_user_up when in data entry? I'll try it out and see what happens, but am interested in your opinion. I'm not sure of the impact to all of the elements.

Thanks!

Chad

If the GRIDLIST (or any other dialog) is larger than the display, then the results are not defined.

You can always define your own event handler. In an .ino (.pde) file it might look like this:

extern "C" uint8_t my_m2_eh_6bs(m2_p ep, uint8_t msg, uint8_t arg1, uint8_t arg2)
{
  m2_nav_p nav = m2_get_nav(ep);
  switch(msg)
  {
    case M2_EP_MSG_SELECT:
      
      /* if the field has data entry, than increment the data */
      if ( m2_nav_is_data_entry(nav) )
	return m2_nav_data_up(m2_get_nav(ep));
      
      /* else go down: do not use m2_nav_down, instead use m2_nav_user_down to skip design elements */
      return m2_nav_user_down(nav, 1);

    case M2_EP_MSG_EXIT:
      return m2_nav_user_up(m2_get_nav(ep));
      
    case M2_EP_MSG_NEXT:
      return m2_nav_user_next(m2_get_nav(ep));

    case M2_EP_MSG_PREV:
      return m2_nav_user_prev(m2_get_nav(ep));
    
    case M2_EP_MSG_DATA_DOWN:
	if ( m2_nav_data_down(nav) == 0 )
          return m2_nav_user_next(nav);
        return 1;
    case M2_EP_MSG_DATA_UP:
	if ( m2_nav_data_up(nav) == 0 )
          return m2_nav_user_prev(nav);
        return 1;
  }
  return 0;
}

I think, what you mean is this:

extern "C" uint8_t my_m2_eh_6bs(m2_p ep, uint8_t msg, uint8_t arg1, uint8_t arg2)
{
  m2_nav_p nav = m2_get_nav(ep);
  switch(msg)
  {
    case M2_EP_MSG_SELECT:
      
      /* if the field has data entry, than increment the data */
      if ( m2_nav_is_data_entry(nav) )
	return m2_nav_user_up(m2_get_nav(ep));   // THIS HAS CHANGED
      
      /* else go down: do not use m2_nav_down, instead use m2_nav_user_down to skip design elements */
      return m2_nav_user_down(nav, 1);

    case M2_EP_MSG_EXIT:
      return m2_nav_user_up(m2_get_nav(ep));
      
    case M2_EP_MSG_NEXT:
      return m2_nav_user_next(m2_get_nav(ep));

    case M2_EP_MSG_PREV:
      return m2_nav_user_prev(m2_get_nav(ep));
    
    case M2_EP_MSG_DATA_DOWN:
	if ( m2_nav_data_down(nav) == 0 )
          return m2_nav_user_next(nav);
        return 1;
    case M2_EP_MSG_DATA_UP:
	if ( m2_nav_data_up(nav) == 0 )
          return m2_nav_user_prev(nav);
        return 1;
  }
  return 0;
}

yes, could be a nice idea...

Oliver