Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M5Button now also on 3-button M5Stack device. Draws button graphics. Events – tap, dbltap, longpress, repeat – for buttons. Extensive documentation and examples. #232

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions examples/Basics/Buttons_and_Events/Buttons_and_Events.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <M5Stack.h>

void setup() {
M5.begin();
M5.BtnA.setLabel("Test");
M5.BtnB.setLabel("Wow !");
M5.BtnC.setLabel("Amazing !");
M5.BtnA.off = M5.BtnB.off = M5.BtnC.off = {BLUE, WHITE, NODRAW};
M5.BtnA.on = M5.BtnB.on = M5.BtnC.on = {RED, WHITE, NODRAW};
M5.Buttons.addHandler(eventDisplay);
M5.Buttons.draw();
}

void loop() {
M5.update();
}

void eventDisplay(Event& e) {
Serial.printf("\n%-12s %-18s", e.typeName(), e.objName());
if (e.type == E_RELEASE || e.type == E_PRESSED) Serial.printf("%5d ms", e.duration);
}
60 changes: 60 additions & 0 deletions examples/M5Button/Combi_Buttons_AB_BC/Combi_Buttons_AB_BC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*

This example will show that the original buttons will not fire any
high-level events after the combinations of buttons are detected, and their
buttons will generate these events instead. Notice how it is not printing
the low-level (E_TOUCH and E_RELEASE) events to not clutter the display.

See https://github.com/m5stack/M5Stack/blob/master/src/utility/M5Button.h
for complete documentation of buttons and events.

*/

#include <M5Stack.h>

// Shortcuts: the & means it's a reference to the same object
Button& A = M5.BtnA;
Button& B = M5.BtnB;
Button& C = M5.BtnC;

// New buttons, not tied to hardware pins
Button AB = Button(55, 193, 102, 21, true, "BtnAB");
Button BC = Button(161, 193, 102, 21, true, "BtnBC");

void setup() {
M5.begin();
A.off = B.off = C.off = AB.off = BC.off = {BLUE, WHITE, NODRAW};
A.on = B.on = C.on = AB.on = BC.on = {RED, WHITE, NODRAW};
M5.Buttons.draw();
M5.Buttons.addHandler(eventDisplay, E_ALL - E_TOUCH - E_RELEASE);
M5.Buttons.addHandler(buttonDown, E_TOUCH);
M5.Buttons.addHandler(buttonUp, E_RELEASE);
}

void loop() {
M5.update();
}

void buttonDown(Event& e) {
if (A && B && !AB) {
A.cancel();
B.cancel();
AB.fingerDown();
}
if (B && C && !BC) {
B.cancel();
C.cancel();
BC.fingerDown();
}
}

void buttonUp(Event& e) {
if (AB && !(A && B)) AB.fingerUp();
if (BC && !(B && C)) BC.fingerUp();
}


void eventDisplay(Event& e) {
Serial.printf("%-14s %-18s %5d ms\n", e.typeName(), e.objName(),
e.duration);
}
12 changes: 12 additions & 0 deletions examples/M5Button/Responsive_Labels/Responsive_Labels.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <M5Stack.h>

void setup() {
M5.BtnA.off = M5.BtnB.off = M5.BtnC.off = {BLUE, WHITE, NODRAW};
M5.BtnA.on = M5.BtnB.on = M5.BtnC.on = {RED, WHITE, NODRAW};
M5.begin();
M5.Buttons.draw();
}

void loop() {
M5.update();
}
97 changes: 96 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,104 @@ BtnC KEYWORD1
begin KEYWORD2
update KEYWORD2
Power KEYWORD2


# Zone
Zone KEYWORD1
rot1 KEYWORD2
set KEYWORD2
contains KEYWORD2
rotate KEYWORD2

# Point
Point KEYWORD1
in KEYWORD2
Equals KEYWORD2
distanceTo KEYWORD2
directionTo KEYWORD2
isDirectionTo KEYWORD2
valid KEYWORD2

ButtonColors KEYWORD1
bg KEYWORD2
text KEYWORD2
outline KEYWORD2

Event KEYWORD1
TFT_eSPI_Button KEYWORD1

instance KEYWORD2
instances KEYWORD2

#Events
fireEvent KEYWORD2
typeName KEYWORD2
objName KEYWORD2
finger KEYWORD2
type KEYWORD2
from KEYWORD2
to KEYWORD2
duration KEYWORD2
distance KEYWORD2
direction KEYWORD2
isDirection KEYWORD2
button KEYWORD2
gesture KEYWORD2

E_TOUCH LITERAL1
E_RELEASE LITERAL1
E_MOVE LITERAL1
E_GESTURE LITERAL1
E_TAP LITERAL1
E_DBLTAP LITERAL1
E_DRAGGED LITERAL1
E_PRESSED LITERAL1
E_PRESSING LITERAL1
E_LONGPRESSED LITERAL1
E_LONGPRESSING LITERAL1

UP LITERAL1
DOWN LITERAL1
LEFT LITERAL1
RIGHT LITERAL1

# Button
Button KEYWORD1
isPressed KEYWORD2
wasPressed KEYWORD2
pressedFor KEYWORD2

isReleased KEYWORD2
wasReleased KEYWORD2
releasedFor KEYWORD2
wasReleasefor KEYWORD2
addHandler KEYWORD2
delHandlers KEYWORD2
lastChange KEYWORD2
cancel KEYWORD2
fingerDown KEYWORD2
fingerUp KEYWORD2
fingerMove KEYWORD2
name KEYWORD2
setLabel KEYWORD2
event KEYWORD2
tapTime KEYWORD2
dbltapTime KEYWORD2
longpressTime KEYWORD2
instanceIndex KEYWORD2
drawFn KEYWORD2
repeatDelay KEYWORD2
repeatinterval KEYWORD2
on KEYWORD2
off KEYWORD2
dx KEYWORD2
dy KEYWORD2


#Buttons
Buttons KEYWORD1
draw KEYWORD2
which KEYWORD2
fireEvent KEYWORD2

held KEYWORD2
repeat KEYWORD2
Expand Down Expand Up @@ -72,8 +162,12 @@ textWrap KEYWORD2
fontWidth KEYWORD2
fontHeight KEYWORD2
setFont KEYWORD2
setTextFont KEYWORD2
setFreeFont KEYWORD2
setTextColor KEYWORD2
setTextSize KEYWORD2
pushState KEYWORD2
popState KEYWORD2

WHITE LITERAL1
BLACK LITERAL1
Expand All @@ -82,3 +176,4 @@ GRAY LITERAL1
RED LITERAL1
BLUE LITERAL1
GREEN LITERAL1
NODRAW LITERAL1
81 changes: 79 additions & 2 deletions src/M5Display.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
#include "M5Display.h"

#ifdef M5Stack_M5Core2
#include <M5Touch.h>
#endif /* M5Stack_M5Core2 */

#define BLK_PWM_CHANNEL 7 // LEDC_CHANNEL_7

M5Display::M5Display() : TFT_eSPI() {}
// So we can use this instance without including all of M5Core2 / M5Stack
M5Display* M5Display::instance;

M5Display::M5Display() : TFT_eSPI() {
if (!instance) instance = this;
}

void M5Display::begin() {
TFT_eSPI::begin();
Expand Down Expand Up @@ -39,7 +48,7 @@ void M5Display::drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const u
}

void M5Display::drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, uint16_t *data) {
bool swap = getSwapBytes();
bool swap = getSwapBytes();
setSwapBytes(true);
pushImage((int32_t)x0, (int32_t)y0, (uint32_t)w, (uint32_t)h, data);
setSwapBytes(swap);
Expand Down Expand Up @@ -607,3 +616,71 @@ void M5Display::drawPngUrl(const char *url, uint16_t x, uint16_t y,
pngle_destroy(pngle);
http.end();
}


// Saves and restores font properties, datum, cursor, colors

void M5Display::pushState() {
DisplayState s;
s.textfont = textfont;
s.textsize = textsize;
s.textcolor = textcolor;
s.textbgcolor = textbgcolor;
s.cursor_x = cursor_x;
s.cursor_y = cursor_y;
s.padX = padX;
s.gfxFont = gfxFont;
_displayStateStack.push_back(s);
}

void M5Display::popState() {
if (_displayStateStack.empty()) return;
DisplayState s = _displayStateStack.back();
_displayStateStack.pop_back();
textfont = s.textfont;
textsize = s.textsize;
textcolor = s.textcolor;
textbgcolor = s.textbgcolor;
cursor_x = s.cursor_x;
cursor_y = s.cursor_y;
padX = s.padX;
if (s.gfxFont && s.gfxFont != gfxFont) setFreeFont(s.gfxFont);
}

#ifdef M5Stack_M5Core2

#ifdef TFT_eSPI_TOUCH_EMULATION

// Emulates the native (resistive) TFT_eSPI touch interface using M5.Touch

uint8_t M5Display::getTouchRaw(uint16_t *x, uint16_t *y) {
return getTouch(x, y);
}

uint16_t M5Display::getTouchRawZ(void) {
return (TOUCH->ispressed()) ? 1000 : 0;
}

void M5Display::convertRawXY(uint16_t *x, uint16_t *y) { return; }

uint8_t M5Display::getTouch(uint16_t *x, uint16_t *y,
uint16_t threshold /* = 600 */) {
TOUCH->read();
if (TOUCH->points) {
*x = TOUCH->point[0].x;
*y = TOUCH->point[0].y;
return true;
}
return false;
}

void M5Display::calibrateTouch(uint16_t *data, uint32_t color_fg,
uint32_t color_bg, uint8_t size) {
return;
}

void M5Display::setTouch(uint16_t *data) { return; }

#endif /* TFT_eSPI_TOUCH_EMULATION */

#endif /* M5Stack_M5Core2 */
46 changes: 42 additions & 4 deletions src/M5Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <Arduino.h>
#include <FS.h>
#include <SPI.h>

#include "utility/Config.h" // This is where Core2 defines would be
#include "utility/In_eSPI.h"
#include "utility/Sprite.h"

Expand All @@ -15,8 +17,16 @@
JPEG_DIV_MAX
} jpeg_div_t;

struct DisplayState {
uint8_t textfont, textsize, datum;
const GFXfont *gfxFont;
uint32_t textcolor, textbgcolor;
int32_t cursor_x, cursor_y, padX;
};

class M5Display : public TFT_eSPI {
public:
static M5Display* instance;
M5Display();
void begin();
void sleep();
Expand All @@ -38,7 +48,7 @@
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL)
if(!inTransaction) {
if (!locked) {
locked = true;
locked = true;
SPI.endTransaction();
}
}
Expand Down Expand Up @@ -92,6 +102,34 @@
uint16_t offX = 0, uint16_t offY = 0,
double scale = 1.0, uint8_t alphaThreshold = 127);

private:
};
#endif
// Saves and restores font properties, datum, cursor and colors so
// code can be non-invasive. Just make sure that every push is also
// popped when you're done to prevent stack from growing.
//
// (User code can never do this completely because the gfxFont
// class variable of TFT_eSPI is protected.)
#define M5DISPLAY_HAS_PUSH_POP
public:
void pushState();
void popState();

private:
std::vector<DisplayState> _displayStateStack;

#ifdef M5Stack_M5Core2

#ifdef TFT_eSPI_TOUCH_EMULATION
// Emulates the TFT_eSPI touch interface using M5.Touch
public:
uint8_t getTouchRaw(uint16_t *x, uint16_t *y);
uint16_t getTouchRawZ(void);
void convertRawXY(uint16_t *x, uint16_t *y);
uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg,
uint8_t size);
void setTouch(uint16_t *data);
#endif /* TFT_eSPI_TOUCH_EMULATION */

#endif /* M5Stack_M5Core2 */
};
#endif /* _M5DISPLAY_H_ */
Loading