Skip to content

Commit 87bae36

Browse files
author
dave
committed
ESP32 LCD example completed
1 parent 9210ad5 commit 87bae36

File tree

7 files changed

+240
-9
lines changed

7 files changed

+240
-9
lines changed

examples/esp32Lcd/Esp32Lcd.emf

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,12 @@
114114
"parentId": 6,
115115
"type": "boolItem",
116116
"item": {
117-
"naming": "TRUE_FALSE",
117+
"naming": "ON_OFF",
118118
"name": "LED1",
119119
"variableName": "GridLED1",
120120
"id": 7,
121121
"eepromAddress": -1,
122+
"functionName": "onGridLed1",
122123
"readOnly": false,
123124
"localOnly": false,
124125
"visible": true
@@ -128,11 +129,12 @@
128129
"parentId": 6,
129130
"type": "boolItem",
130131
"item": {
131-
"naming": "TRUE_FALSE",
132+
"naming": "ON_OFF",
132133
"name": "LED2",
133134
"variableName": "GridLED2",
134135
"id": 8,
135136
"eepromAddress": -1,
137+
"functionName": "onGridLed2",
136138
"readOnly": false,
137139
"localOnly": false,
138140
"visible": true
@@ -146,6 +148,7 @@
146148
"variableName": "GridUp",
147149
"id": 10,
148150
"eepromAddress": -1,
151+
"functionName": "onGridUp",
149152
"readOnly": false,
150153
"localOnly": false,
151154
"visible": true
@@ -159,6 +162,7 @@
159162
"variableName": "GridDown",
160163
"id": 11,
161164
"eepromAddress": -1,
165+
"functionName": "onGridDown",
162166
"readOnly": false,
163167
"localOnly": false,
164168
"visible": true
@@ -169,7 +173,7 @@
169173
"embeddedPlatform": "ARDUINO_ESP32",
170174
"lastDisplayUuid": "d4c84106-fa87-4024-b91e-053e17a52b8f",
171175
"lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87",
172-
"lastRemoteUuid": "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb",
176+
"lastRemoteUuid": "ba23b2a7-040e-40e2-8fae-d45c82cf450b",
173177
"lastThemeUuid": "850dc0a3-f534-47c2-94d8-1e64ff368a54",
174178
"applicationUUID": "7833942f-2ef4-486f-9713-045552b747e8",
175179
"applicationName": "Esp32Lcd",
@@ -254,6 +258,16 @@
254258
"latestValue": "false",
255259
"subsystem": "INPUT"
256260
},
261+
{
262+
"name": "SERIAL_PORT",
263+
"latestValue": "Serial",
264+
"subsystem": "REMOTE"
265+
},
266+
{
267+
"name": "HARDWARE_PORT",
268+
"latestValue": "true",
269+
"subsystem": "REMOTE"
270+
},
257271
{
258272
"name": "ITEM_FONT",
259273
"latestValue": "def:,1",
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2018 https://www.thecoderscorner.com (Nutricherry LTD).
3+
* This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4+
*/
5+
6+
/**
7+
* Serial remote capability plugin. This file is a plugin file and should not be directly edited,
8+
* it will be replaced each time the project is built. If you want to edit this file in place,
9+
* make sure to rename it first.
10+
*/
11+
12+
#include "SerialTransport.h"
13+
#include <tcMenu.h>
14+
#include <MessageProcessors.h>
15+
16+
SerialTagValServer remoteServer;
17+
18+
SerialTagValueTransport::SerialTagValueTransport() : TagValueTransport() {
19+
this->serialPort = NULL;
20+
}
21+
22+
void SerialTagValueTransport::close() {
23+
currentField.msgType = UNKNOWN_MSG_TYPE;
24+
currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG;
25+
}
26+
27+
void SerialTagValServer::begin(HardwareSerial* portStream, const ConnectorLocalInfo* localInfo) {
28+
serPort.setStream(portStream);
29+
connector.initialise(&serPort, &messageProcessor, localInfo);
30+
taskManager.scheduleFixedRate(TICK_INTERVAL, []{remoteServer.runLoop();}, TIME_MILLIS);
31+
}
32+
33+
SerialTagValServer::SerialTagValServer() : messageProcessor(msgHandlers, MSG_HANDLERS_SIZE) {
34+
}
35+
36+
37+
// DO NOT replace this with the standard char* write method on serial.
38+
// It cannot handle large volumes of data going through at once and often
39+
// overflows the buffer causing data errors.
40+
int SerialTagValueTransport::writeChar(char ch) {
41+
if(available()) {
42+
serialPort->write(ch);
43+
}
44+
else {
45+
int tries = 30;
46+
while(tries && !available()) {
47+
--tries;
48+
serialPort->flush();
49+
taskManager.yieldForMicros(100);
50+
}
51+
52+
// if it's not available now, it probably will timeout anyway.
53+
if(!available()) {
54+
return 0;
55+
}
56+
57+
serialPort->write(ch);
58+
}
59+
return 1;
60+
}
61+
62+
int SerialTagValueTransport::writeStr(const char* str) {
63+
int i=0;
64+
bool lastWriteOk = true;
65+
while(str[i] && lastWriteOk) {
66+
lastWriteOk = writeChar(str[i]);
67+
i++;
68+
}
69+
return i;
70+
}
71+
72+
void SerialTagValServer::runLoop() {
73+
connector.tick();
74+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2018 https://www.thecoderscorner.com (Nutricherry LTD).
3+
* This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4+
*/
5+
6+
/**
7+
* @file SerialTransport.h
8+
*
9+
* Serial remote capability plugin. This file is a plugin file and should not be directly edited,
10+
* it will be replaced each time the project is built. If you want to edit this file in place,
11+
* make sure to rename it first.
12+
*/
13+
14+
#ifndef _TCMENU_SERIALTRANSPORT_H_
15+
#define _TCMENU_SERIALTRANSPORT_H_
16+
17+
#include <Arduino.h>
18+
#include <RemoteConnector.h>
19+
#include <MessageProcessors.h>
20+
#include <tcUtil.h>
21+
#include <RemoteAuthentication.h>
22+
23+
/**
24+
* Serial transport is an implementation of TagValueTransport that works over a serial port
25+
*/
26+
class SerialTagValueTransport : public TagValueTransport {
27+
private:
28+
HardwareSerial* serialPort;
29+
public:
30+
SerialTagValueTransport();
31+
virtual ~SerialTagValueTransport() {}
32+
void setStream(HardwareSerial* stream) {this->serialPort = stream; }
33+
34+
void flush() override {serialPort->flush();}
35+
int writeChar(char data) override;
36+
int writeStr(const char* data) override;
37+
38+
uint8_t readByte() override { return serialPort->read(); }
39+
bool readAvailable() override { return serialPort->available(); }
40+
bool available() override { return serialPort->availableForWrite() != 0;}
41+
bool connected() override { return true;}
42+
43+
void close() override;
44+
45+
};
46+
47+
/**
48+
* SerialTagValServer is the implementation of remote communication that provides
49+
* remote menu capability for Serial streams.
50+
*/
51+
class SerialTagValServer {
52+
private:
53+
SerialTagValueTransport serPort;
54+
TagValueRemoteConnector connector;
55+
CombinedMessageProcessor messageProcessor;
56+
public:
57+
/** Empty constructor - configured in begin */
58+
SerialTagValServer();
59+
60+
/**
61+
* Sets the mode of authentication used with your remote, if you don't call this the system will
62+
* default to no authentication; which is probably fine for serial / bluetooth serial.
63+
*
64+
* This should always be called before begin(), to ensure this in your code always ensure this
65+
* is called BEFORE setupMenu().
66+
*
67+
* @param authManager a reference to an authentication manager.
68+
*/
69+
void setAuthenticator(AuthenticationManager* authManager) { connector.setAuthManager(authManager); }
70+
71+
/**
72+
* Begins serial communication on the given port. You must call begin on the stream first.
73+
* @param portStream the stream upon which to communicate, it must be already opened.
74+
* @param namePgm the local name of the application (may be program memory on AVR use safeCopyStr)
75+
*/
76+
void begin(HardwareSerial* portStream, const ConnectorLocalInfo* localInfo);
77+
78+
/**
79+
* Arranged internally don't call yourself.
80+
*/
81+
void runLoop();
82+
83+
/** @return the remote connector associated with the connection */
84+
TagValueRemoteConnector* getRemoteConnector(int /*num*/) {return &connector;}
85+
86+
/** @return the transport that's associated with the connection */
87+
SerialTagValueTransport* getTransport(int /*num*/) {return &serPort;}
88+
};
89+
90+
/**
91+
* the global instance of the SerialTagValServer
92+
*/
93+
extern SerialTagValServer remoteServer;
94+
95+
#endif /* _TCMENU_SERIALTRANSPORT_H_ */

examples/esp32Lcd/esp32Lcd.ino

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
11
#include "esp32Lcd_menu.h"
22

3+
//
4+
// Creating a grid layout just for a specific menu item. The flags menu under additional is laid out in a grid format,
5+
// where the menu items are presented two per row.
6+
//
7+
void prepareLayout() {
8+
auto& factory = renderer.getLcdDisplayPropertiesFactory();
9+
// we now create a grid for the two led controls in the submenu, this shows how to override the default grid for a few items.
10+
// In most cases the automatic rendering works fine when a few items are overriden as long as the row you request hasn't yet been taken.
11+
factory.addGridPosition(&menuGridLED1,
12+
GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, 2, 1, 2, 1));
13+
factory.addGridPosition(&menuGridLED2,
14+
GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_RIGHT_WITH_VALUE, 2, 2, 2, 1));
15+
factory.addGridPosition(&menuGridUp,
16+
GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_LEFT_NO_VALUE, 2, 1, 3, 1));
17+
factory.addGridPosition(&menuGridDown,
18+
GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_RIGHT_NO_VALUE, 2, 2, 3, 1));
19+
}
20+
321
void setup() {
422
Serial.begin(115200);
523
Wire.begin(4, 15);
24+
25+
// define the number of rows in the list, lists really don't like 0 rows much.
26+
menuMyList.setNumberOfRows(5);
27+
28+
// prepare the grid layout for our grid example
29+
prepareLayout();
30+
31+
// now call setupMenu to prepare the menu system.
632
setupMenu();
733
}
834

@@ -30,3 +56,17 @@ int CALLBACK_FUNCTION fnMyListRtCall(RuntimeMenuItem* item, uint8_t row, RenderF
3056
default: return false;
3157
}
3258
}
59+
60+
void CALLBACK_FUNCTION onGridLed2(int id) {
61+
}
62+
63+
void CALLBACK_FUNCTION onGridLed1(int id) {
64+
}
65+
66+
void CALLBACK_FUNCTION onGridDown(int id) {
67+
menuGridFloatValue.setFloatValue(menuGridFloatValue.getFloatValue() - 0.333F);
68+
}
69+
70+
void CALLBACK_FUNCTION onGridUp(int id) {
71+
menuGridFloatValue.setFloatValue(menuGridFloatValue.getFloatValue() + 0.333F);
72+
}

examples/esp32Lcd/esp32Lcd_menu.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ LiquidCrystalRenderer renderer(lcd, 20, 4);
1919

2020
// Global Menu Item declarations
2121

22-
const PROGMEM AnyMenuInfo minfoGridDown = { "Down", 11, 0xffff, 0, NO_CALLBACK };
22+
const PROGMEM AnyMenuInfo minfoGridDown = { "Down", 11, 0xffff, 0, onGridDown };
2323
ActionMenuItem menuGridDown(&minfoGridDown, NULL);
24-
const PROGMEM AnyMenuInfo minfoGridUp = { "Up", 10, 0xffff, 0, NO_CALLBACK };
24+
const PROGMEM AnyMenuInfo minfoGridUp = { "Up", 10, 0xffff, 0, onGridUp };
2525
ActionMenuItem menuGridUp(&minfoGridUp, &menuGridDown);
26-
const PROGMEM BooleanMenuInfo minfoGridLED2 = { "LED2", 8, 0xffff, 1, NO_CALLBACK, NAMING_TRUE_FALSE };
26+
const PROGMEM BooleanMenuInfo minfoGridLED2 = { "LED2", 8, 0xffff, 1, onGridLed2, NAMING_ON_OFF };
2727
BooleanMenuItem menuGridLED2(&minfoGridLED2, false, &menuGridUp);
28-
const PROGMEM BooleanMenuInfo minfoGridLED1 = { "LED1", 7, 0xffff, 1, NO_CALLBACK, NAMING_TRUE_FALSE };
28+
const PROGMEM BooleanMenuInfo minfoGridLED1 = { "LED1", 7, 0xffff, 1, onGridLed1, NAMING_ON_OFF };
2929
BooleanMenuItem menuGridLED1(&minfoGridLED1, false, &menuGridLED2);
3030
const PROGMEM FloatMenuInfo minfoGridFloatValue = { "Float value", 9, 0xffff, 3, NO_CALLBACK };
3131
FloatMenuItem menuGridFloatValue(&minfoGridFloatValue, &menuGridLED1);
@@ -59,5 +59,6 @@ void setupMenu() {
5959
lcd.backlight();
6060
switches.initialiseInterrupt(internalDigitalIo(), true);
6161
menuMgr.initForEncoder(&renderer, &menuPercentage, 26, 36, 21);
62+
remoteServer.begin(&Serial, &applicationInfo);
6263
}
6364

examples/esp32Lcd/esp32Lcd_menu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <Wire.h>
1717
#include <LiquidCrystalIO.h>
1818
#include <IoAbstractionWire.h>
19+
#include <RemoteConnector.h>
20+
#include "SerialTransport.h"
1921
#include <ScrollChoiceMenuItem.h>
2022
#include <RuntimeMenuItem.h>
2123
#include "tcMenuLiquidCrystal.h"
@@ -50,5 +52,9 @@ inline MenuItem& rootMenuItem() { return menuPercentage; }
5052
#define CALLBACK_FUNCTION
5153

5254
int fnMyListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
55+
void CALLBACK_FUNCTION onGridDown(int id);
56+
void CALLBACK_FUNCTION onGridLed1(int id);
57+
void CALLBACK_FUNCTION onGridLed2(int id);
58+
void CALLBACK_FUNCTION onGridUp(int id);
5359

5460
#endif // MENU_GENERATED_CODE_H

examples/esp32Lcd/tcMenuLiquidCrystal.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ void LiquidCrystalRenderer::drawMenuItem(GridPositionRowCacheEntry* entry, Coord
100100
menuValueToText(theItem, JUSTIFY_TEXT_RIGHT);
101101
}
102102
else {
103-
char sz[22];
104-
for(uint8_t i = 1; i < (uint8_t)areaSize.x; ++i) buffer[i] = 32;
103+
char sz[21];
104+
for(uint8_t i = 1; i < (sizeof(sz) - 1); ++i) buffer[i] = 32;
105+
buffer[sizeof(sz)-1] = 0;
105106
uint8_t valueStart = 0;
106107
if(itemNeedsName(entry->getPosition().getJustification())) {
107108
theItem->copyNameToBuffer(sz, sizeof sz);

0 commit comments

Comments
 (0)