Skip to content

Commit f694801

Browse files
author
dave
committed
More example updates for 2.2 release
1 parent 817a6f3 commit f694801

20 files changed

+172
-132
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* This class implements CustomDrawing which means that it can be registered with the renderer
3+
* to be told when the screen is about to reset (become idle basically). This callback will
4+
* also be told when a takeOverDisplay call starts, and then the rendering function is called
5+
* frequently, so you can update the display.
6+
*
7+
* Associated docs:
8+
* https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/renderer-take-over-display/
9+
*/
10+
11+
#ifndef TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H
12+
#define TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H
13+
14+
#include <BaseRenderers.h>
15+
#include "colorTftEthernet32_menu.h"
16+
17+
class ColorEthernetCustomDraw : public CustomDrawing {
18+
public:
19+
void reset() override {
20+
// When the display becomes idle, we take over the display, the no-arg version is
21+
// used to indicate you want the custom draw class to do the rendering.
22+
renderer.takeOverDisplay();
23+
}
24+
25+
void started(BaseMenuRenderer *currentRenderer) override {
26+
// you need to handle the clearing and preparation of the display when first called.
27+
switches.getEncoder()->changePrecision(1000, 500);
28+
gfx.setCursor(0, 0);
29+
gfx.fillRect(0, 0, gfx.width(), gfx.height(), BLACK);
30+
gfx.setFont(nullptr);
31+
gfx.setTextSize(2);
32+
gfx.print("Encoder ");
33+
}
34+
35+
36+
void renderLoop(unsigned int currentValue, RenderPressMode pressType) override {
37+
// if the encoder / select button is held, we go back to the menu.
38+
if(pressType == RPRESS_HELD) {
39+
renderer.giveBackDisplay();
40+
return;
41+
}
42+
43+
GFXcanvas1 canvas(100, 20);
44+
canvas.fillScreen(BLACK);
45+
canvas.setCursor(0,0);
46+
canvas.print(currentValue);
47+
canvas.setTextSize(2);
48+
gfx.drawBitmap(0, 35, canvas.getBuffer(), 100, 20, WHITE, BLACK);
49+
50+
}
51+
};
52+
53+
#endif //TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H

examples/colorTftEthernet32/EthernetTransport.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ void EthernetTagValTransport::flush() {
3333
client.flush();
3434
}
3535
else {
36-
client.stop();
36+
writeBufferPos = 0;
37+
close();
3738
}
3839
}
3940

examples/colorTftEthernet32/ThemeCoolBlueTraditional.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
// tcMenu drawing properties take a 4 color palette for items, titles and actions.
99
// this renderer shares the color configuration for items and actions.
10-
color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(0,133,255)};
11-
color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)};
10+
const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)};
11+
const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)};
1212

1313
void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) {
1414
// first we keep a reference to the screen size, and set the dimensions on the renderer.
@@ -25,7 +25,7 @@ void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFont
2525
// here we calculate the item padding and row heights based on the resolution of the display
2626
bool medResOrBetter = width > 160;
2727
MenuPadding titlePadding(medResOrBetter ? 4 : 2);
28-
MenuPadding itemPadding(2);
28+
MenuPadding itemPadding(medResOrBetter ? 2 : 1);
2929
int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding);
3030
int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding);
3131

examples/colorTftEthernet32/colorTftEthernet.emf

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@
505505
},
506506
{
507507
"name": "TITLE_FONT",
508-
"latestValue": "def:,1",
508+
"latestValue": "ada:FreeSansBold9pt7b,1",
509509
"subsystem": "THEME"
510510
},
511511
{
@@ -533,6 +533,10 @@
533533
"saveToSrc": false,
534534
"useCppMain": false,
535535
"eepromDefinition": "at24:80:PAGESIZE_AT24C128",
536-
"authenticatorDefinition": "rom:100:6"
536+
"authenticatorDefinition": "rom:100:6",
537+
"projectIoExpanders": [
538+
"deviceIO:",
539+
"pcf8574:io8574:32:0"
540+
]
537541
}
538542
}

examples/colorTftEthernet32/colorTftEthernet32.ino

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <Ethernet.h>
88
#include <SPI.h>
99
#include <IoLogging.h>
10+
#include "ColorEtherenetCustomDraw.h"
11+
#include <tcMenuVersion.h>
1012

1113
// contains the graphical widget title components.
1214
#include "stockIcons/wifiAndConnectionIcons16x12.h"
@@ -25,16 +27,21 @@ byte mac[] = {
2527
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
2628
};
2729

28-
// then we setup the IO expander that the also set up in the designer for input.
29-
IoAbstractionRef io8574 = ioFrom8574(0x20, 0); // on addr 0x20 and interrupt pin 0
30-
3130
// and we create an analog device with enhanced range because we are using a 32bit board.
3231
ArduinoAnalogDevice analogDevice(12, 10);
3332

3433
// We add a title widget that shows when a user is connected to the device. Connection icons
3534
// are in the standard icon set we included at the top.
3635
TitleWidget connectedWidget(iconsConnection, 2, 16, 12);
3736

37+
// We also want to take over the display whenever the screen becomes idle, here we use the CustomDrawing
38+
// technique described in the documentation. See ColorEthernetCustomDraw.h
39+
ColorEthernetCustomDraw myCustomDraw;
40+
41+
// Here we declare a string in const/PROGMEM for use with a dialog later. Note that this works even on ARM
42+
// boards that don't have separated program memory.
43+
const char pgmHeaderSavedItem[] PROGMEM = "Rom Item Saved";
44+
3845
// Start 2nd Encoder
3946
// Here, we use a second rotary encoder to adjust one of the menu items, the button toggles a boolean item
4047
// Here are the fields for the second rotary encoder
@@ -49,7 +56,7 @@ const int ledPin = 1;
4956
// when there's a change in communication status (connection or disconnection for example) this gets called.
5057
// see further down in the code where we add this to the remote IoT monitor.
5158
void onCommsChange(CommunicationInfo info) {
52-
if(info.remoteNo == 0) {
59+
if(info.remoteNo == 0U) {
5360
connectedWidget.setCurrentState(info.connected ? 1 : 0);
5461
}
5562
// this relies on logging in IoAbstraction's ioLogging.h, to turn it on visit the file for instructions.
@@ -96,16 +103,29 @@ void setup() {
96103
menuIpAddress.copyValue(sz, sizeof(sz));
97104
Serial.print("Ethernet available on ");Serial.println(sz);
98105

99-
taskManager.scheduleFixedRate(2250, [] {
106+
taskManager.scheduleFixedRate(250, [] {
100107
float a1Value = analogDevice.getCurrentFloat(A1);
101-
menuVoltA1.setFloatValue(a1Value * 3.3);
108+
menuVoltA1.setFloatValue(a1Value * 3.3F);
102109
});
103110

104-
// Start 2nd encoder
105-
Serial.println("Setting up second encoder now");
111+
// register the custom drawing handler
112+
renderer.setCustomDrawingHandler(&myCustomDraw);
106113

107114
ioDevicePinMode(switches.getIoAbstraction(), ledPin, OUTPUT);
108115

116+
setTitlePressedCallback([](int id) {
117+
withMenuDialogIfAvailable([](MenuBasedDialog* dlg) {
118+
dlg->setButtons(BTNTYPE_CLOSE, BTNTYPE_NONE);
119+
dlg->showRam("ARM Example", false);
120+
char menuVer[10];
121+
tccore::copyTcMenuVersion(menuVer, sizeof menuVer);
122+
dlg->copyIntoBuffer(menuVer);
123+
});
124+
});
125+
126+
// Start 2nd encoder
127+
Serial.println("Setting up second encoder now");
128+
109129
// here we want the encoder set to the range of values that menuCurrent takes, this is just for example,
110130
// and you could set the range to anything that is required. We use the callback to update the menu item.
111131
secondEncoder = new HardwareRotaryEncoder(encoder2APin, encoder2BPin, [](int encoderValue) {
@@ -131,8 +151,8 @@ void writeToDac() {
131151
float volts = menuVoltage.getAsFloatingPointValue();
132152
float curr = menuCurrent.getAsFloatingPointValue();
133153

134-
float total = (volts / 64.0) * (curr / 2.0);
135-
analogDevice.setCurrentFloat(A0, (unsigned int)total);
154+
float total = (volts / 64.0F) * (curr / 2.0F);
155+
analogDevice.setCurrentFloat(A0, total);
136156
menuVoltA0.setFloatValue(total);
137157
}
138158

@@ -153,42 +173,8 @@ void CALLBACK_FUNCTION onSaveRom(int /*id*/) {
153173
menuMgr.save();
154174
}
155175

156-
bool starting = true;
157-
158-
const char pgmHeaderSavedItem[] PROGMEM = "Rom Item Saved";
159-
160-
void myRenderCallback(unsigned int encoderVal, RenderPressMode pressType) {
161-
if(pressType == RPRESS_HELD)
162-
{
163-
// if the encoder / select button is held, we go back to the menu.
164-
renderer.giveBackDisplay();
165-
}
166-
else if(starting)
167-
{
168-
// you need to handle the clearing and preparation of the display when you're first called.
169-
// the easiest way is to set a flag such as this and then prepare the display.
170-
starting = false;
171-
switches.getEncoder()->changePrecision(1000, 500);
172-
gfx.setCursor(0, 0);
173-
gfx.fillRect(0, 0, gfx.width(), gfx.height(), BLACK);
174-
gfx.setFont(nullptr);
175-
gfx.setTextSize(2);
176-
gfx.print("Encoder ");
177-
}
178-
else
179-
{
180-
GFXcanvas1 canvas(100, 20);
181-
canvas.fillScreen(BLACK);
182-
canvas.setCursor(0,0);
183-
canvas.print(encoderVal);
184-
canvas.setTextSize(2);
185-
gfx.drawBitmap(0, 35, canvas.getBuffer(), 100, 20, WHITE, BLACK);
186-
}
187-
}
188-
189176
void CALLBACK_FUNCTION onTakeDisplay(int /*id*/) {
190-
starting = true;
191-
renderer.takeOverDisplay(myRenderCallback);
177+
renderer.takeOverDisplay();
192178
}
193179

194180
void CALLBACK_FUNCTION onRgbChanged(int /*id*/) {
@@ -225,7 +211,7 @@ void CALLBACK_FUNCTION onRomLocationChange(int /*id*/) {
225211
int CALLBACK_FUNCTION fnRomLocationRtCall(RuntimeMenuItem * item, uint8_t row, RenderFnMode mode, char * buffer, int bufferSize) {
226212
switch(mode) {
227213
case RENDERFN_INVOKE:
228-
onRomLocationChange(item->getId());
214+
onRomLocationChange(int(item->getId()));
229215
return true;
230216
case RENDERFN_NAME:
231217
// TODO - each row has it's own name - 0xff is the parent item

examples/colorTftEthernet32/colorTftEthernet32.ino.backup

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <Ethernet.h>
88
#include <SPI.h>
99
#include <IoLogging.h>
10+
#include "ColorEtherenetCustomDraw.h"
1011

1112
// contains the graphical widget title components.
1213
#include "stockIcons/wifiAndConnectionIcons16x12.h"
@@ -25,16 +26,21 @@ byte mac[] = {
2526
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
2627
};
2728

28-
// then we setup the IO expander that the also set up in the designer for input.
29-
IoAbstractionRef io8574 = ioFrom8574(0x20, 0); // on addr 0x20 and interrupt pin 0
30-
3129
// and we create an analog device with enhanced range because we are using a 32bit board.
3230
ArduinoAnalogDevice analogDevice(12, 10);
3331

3432
// We add a title widget that shows when a user is connected to the device. Connection icons
3533
// are in the standard icon set we included at the top.
3634
TitleWidget connectedWidget(iconsConnection, 2, 16, 12);
3735

36+
// We also want to take over the display whenever the screen becomes idle, here we use the CustomDrawing
37+
// technique described in the documentation. See ColorEthernetCustomDraw.h
38+
ColorEthernetCustomDraw myCustomDraw;
39+
40+
// Here we declare a string in const/PROGMEM for use with a dialog later. Note that this works even on ARM
41+
// boards that don't have separated program memory.
42+
const char pgmHeaderSavedItem[] PROGMEM = "Rom Item Saved";
43+
3844
// Start 2nd Encoder
3945
// Here, we use a second rotary encoder to adjust one of the menu items, the button toggles a boolean item
4046
// Here are the fields for the second rotary encoder
@@ -101,6 +107,9 @@ void setup() {
101107
menuVoltA1.setFloatValue(a1Value * 3.3);
102108
});
103109

110+
// register the custom drawing handler
111+
renderer.setCustomDrawingHandler(&myCustomDraw);
112+
104113
// Start 2nd encoder
105114
Serial.println("Setting up second encoder now");
106115

@@ -131,8 +140,8 @@ void writeToDac() {
131140
float volts = menuVoltage.getAsFloatingPointValue();
132141
float curr = menuCurrent.getAsFloatingPointValue();
133142

134-
float total = (volts / 64.0) * (curr / 2.0);
135-
analogDevice.setCurrentFloat(A0, (unsigned int)total);
143+
float total = (volts / 64.0F) * (curr / 2.0F);
144+
analogDevice.setCurrentFloat(A0, total);
136145
menuVoltA0.setFloatValue(total);
137146
}
138147

@@ -153,42 +162,8 @@ void CALLBACK_FUNCTION onSaveRom(int /*id*/) {
153162
menuMgr.save();
154163
}
155164

156-
bool starting = true;
157-
158-
const char pgmHeaderSavedItem[] PROGMEM = "Rom Item Saved";
159-
160-
void myRenderCallback(unsigned int encoderVal, RenderPressMode pressType) {
161-
if(pressType == RPRESS_HELD)
162-
{
163-
// if the encoder / select button is held, we go back to the menu.
164-
renderer.giveBackDisplay();
165-
}
166-
else if(starting)
167-
{
168-
// you need to handle the clearing and preparation of the display when you're first called.
169-
// the easiest way is to set a flag such as this and then prepare the display.
170-
starting = false;
171-
switches.getEncoder()->changePrecision(1000, 500);
172-
gfx.setCursor(0, 0);
173-
gfx.fillRect(0, 0, gfx.width(), gfx.height(), BLACK);
174-
gfx.setFont(nullptr);
175-
gfx.setTextSize(2);
176-
gfx.print("Encoder ");
177-
}
178-
else
179-
{
180-
GFXcanvas1 canvas(100, 20);
181-
canvas.fillScreen(BLACK);
182-
canvas.setCursor(0,0);
183-
canvas.print(encoderVal);
184-
canvas.setTextSize(2);
185-
gfx.drawBitmap(0, 35, canvas.getBuffer(), 100, 20, WHITE, BLACK);
186-
}
187-
}
188-
189165
void CALLBACK_FUNCTION onTakeDisplay(int /*id*/) {
190-
starting = true;
191-
renderer.takeOverDisplay(myRenderCallback);
166+
renderer.takeOverDisplay();
192167
}
193168

194169
void CALLBACK_FUNCTION onRgbChanged(int /*id*/) {
@@ -200,7 +175,7 @@ void CALLBACK_FUNCTION onSaveItem(int /*id*/) {
200175
auto itemNo = menuRomLocation.getCurrentValue();
201176
auto itemSize = menuRomChoice.getItemWidth();
202177
auto position = menuRomChoice.getEepromStart() + (itemNo * itemSize);
203-
eeprom.writeArrayToRom(position, (const uint8_t*)menuRomText.getTextValue(), 10);
178+
menuMgr.getEepromAbstraction()->writeArrayToRom(position, (const uint8_t*)menuRomText.getTextValue(), 10);
204179

205180
if(renderer.getDialog()->isInUse()) return;
206181
renderer.getDialog()->setButtons(BTNTYPE_NONE, BTNTYPE_OK);
@@ -212,7 +187,7 @@ void CALLBACK_FUNCTION onRomLocationChange(int /*id*/) {
212187
auto itemNo = menuRomLocation.getCurrentValue();
213188
char sz[12];
214189
auto itemSize = menuRomChoice.getItemWidth();
215-
eeprom.readIntoMemArray((uint8_t*)sz, menuRomChoice.getEepromStart() + (itemNo * itemSize), 10);
190+
menuMgr.getEepromAbstraction()->readIntoMemArray((uint8_t*)sz, menuRomChoice.getEepromStart() + (itemNo * itemSize), 10);
216191
menuRomText.setTextValue(sz);
217192
serdebugF2("Rom data was ", sz)
218193
}
@@ -225,7 +200,7 @@ void CALLBACK_FUNCTION onRomLocationChange(int /*id*/) {
225200
int CALLBACK_FUNCTION fnRomLocationRtCall(RuntimeMenuItem * item, uint8_t row, RenderFnMode mode, char * buffer, int bufferSize) {
226201
switch(mode) {
227202
case RENDERFN_INVOKE:
228-
onRomLocationChange(item->getId());
203+
onRomLocationChange(int(item->getId()));
229204
return true;
230205
case RENDERFN_NAME:
231206
// TODO - each row has it's own name - 0xff is the parent item

examples/colorTftEthernet32/colorTftEthernet32_menu.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#include <tcMenu.h>
1212
#include "colorTftEthernet32_menu.h"
1313
#include "ThemeCoolBlueTraditional.h"
14+
#include <Fonts/FreeSansBold9pt7b.h>
1415

1516
// Global variable declarations
1617
const ConnectorLocalInfo applicationInfo = { "Ada32 Ethernet", "22813e5e-88b1-42d5-9601-4831b2be369b" };
1718
TcMenuRemoteServer remoteServer(applicationInfo);
19+
IoAbstractionRef ioexp_io8574 = ioFrom8574(0x20, 0);
1820
I2cAt24Eeprom glI2cRom(0x50, PAGESIZE_AT24C128);
1921
EepromAuthenticatorManager authManager(6);
2022
Adafruit_ST7735 gfx(6, 7, 3);
@@ -99,12 +101,12 @@ void setupMenu() {
99101
gfx.initR(INITR_BLACKTAB);
100102
gfx.setRotation(1);
101103
renderer.setUpdatesPerSecond(5);
102-
switches.initialiseInterrupt(io8574, true);
104+
switches.initialiseInterrupt(ioexp_io8574, true);
103105
menuMgr.initForEncoder(&renderer, &menuVoltage, 7, 6, 5);
104106
remoteServer.addConnection(&ethernetConnection);
105107
renderer.setTitleMode(BaseGraphicalRenderer::TITLE_ALWAYS);
106108
renderer.setUseSliderForAnalog(true);
107-
installCoolBlueTraditionalTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true);
109+
installCoolBlueTraditionalTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(&FreeSansBold9pt7b, 1), true);
108110

109111
// We have an IoT monitor, register the server
110112
menuIoTMonitor.setRemoteServer(remoteServer);

0 commit comments

Comments
 (0)