Spirik / GEM

Good Enough Menu for Arduino
GNU Lesser General Public License v3.0
239 stars 36 forks source link

Menu controlling via serial port #57

Closed TimonPeng closed 2 years ago

TimonPeng commented 2 years ago

When there aren't enough components around to build a prototype, maybe this is a good way to test.

TimonPeng commented 2 years ago

I have written a demo works with u8g2, it's almost completely copied from your KeyDetector, just for everyone to use and you can close this issue anytime.

SerialKey.h

#ifndef _SERIAL_KEY_H
#define _SERIAL_KEY_H

#include <Arduino.h>
#include <GEM_u8g2.h>

class SerialKey {
 public:
  SerialKey(int up_ascii_, int right_ascii_, int down_ascii_, int left_ascii_,
            int cancel_ascii_, int ok_ascii_);
  byte trigger = GEM_KEY_NONE;
  byte current = GEM_KEY_NONE;
  void detect();

 private:
  int _up_ascii;
  int _right_ascii;
  int _down_ascii;
  int _left_ascii;
  int _cancel_ascii;
  int _ok_ascii;
};

#endif

SerialKey.cpp

#include "SerialKey.h"

#include <Arduino.h>
#include <GEM_u8g2.h>

SerialKey::SerialKey(int up_ascii_, int right_ascii_, int down_ascii_,
                     int left_ascii_, int cancel_ascii_, int ok_ascii_)
    : _up_ascii(up_ascii_),
      _right_ascii(right_ascii_),
      _down_ascii(down_ascii_),
      _left_ascii(left_ascii_),
      _cancel_ascii(cancel_ascii_),
      _ok_ascii(ok_ascii_) {}

void SerialKey::detect() {
  boolean pressed = false;

  if (Serial.available() > 0) {
    int incomingByte = Serial.read();

    // Serial.print("Received: ");
    // Serial.println(incomingByte, DEC);

    if (incomingByte == _up_ascii) {
      current = GEM_KEY_UP;
      pressed = true;
      // Serial.println("Pressed up");
    } else if (incomingByte == _right_ascii) {
      current = GEM_KEY_RIGHT;
      pressed = true;
      // Serial.println("Pressed right");
    } else if (incomingByte == _down_ascii) {
      current = GEM_KEY_DOWN;
      pressed = true;
      // Serial.println("Pressed down");
    } else if (incomingByte == _left_ascii) {
      current = GEM_KEY_LEFT;
      pressed = true;
      // Serial.println("Pressed left");
    } else if (incomingByte == _cancel_ascii) {
      current = GEM_KEY_CANCEL;
      pressed = true;
      // Serial.println("Pressed cancel");
    } else if (incomingByte == _ok_ascii) {
      current = GEM_KEY_OK;
      pressed = true;
      // Serial.println("Pressed ok");
    }
  } else {
    pressed = false;
  }

  if (!pressed) {
    current = GEM_KEY_NONE;
  }

  trigger = current;
}

Usage:

#include "SerialKey.h"

// w (119) -> ↑
// d (100) -> →
// s (115) -> ↓
// a (97) -> ←
// q (113) -> cancel
// e (101) -> ok
SerialKey serialKey(/*Up=*/119, /*Right/Next=*/100,
                    /*Down=*/115, /*Left/Prev=*/97,
                    /*Home/Cancel=*/113, /*Select/OK=*/101);

void loop() {
  if (menu.readyForKey()) {
    serialKey.detect();
    menu.registerKeyPress(serialKey.trigger);
  }

  delay(100);
}
Spirik commented 2 years ago

Oh, that's great! I've just wanted to reply to an original post that it is totally possible to control GEM via Serial from the user sketch (and link to this section of Wiki for details) and you beat me to it with a complete example=)

Thanks for sharing, it can be useful for someone else! I will add link to this solution in wiki=)

Spirik commented 2 years ago

If you change U8g2 specific aliases to more general GEM ones (e.g. U8X8_MSG_GPIO_MENU_UP -> GEM_KEY_UP, etc.) it will be possible to us this example with any versions of GEM (including AltSerialGraphicLCD and Adafruit GFX).

TimonPeng commented 2 years ago

Okay no problem, do you mind if I just edit the file above or should I post the new one below here?

Spirik commented 2 years ago

Feel free to edit your original post, that should be fine!

TimonPeng commented 2 years ago

Done, it's looks good to you?

Spirik commented 2 years ago

Seems to be fine, thank you!

Spirik commented 2 years ago

Link to this example added to Wiki.