1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
#include <Arduino.h>
#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <GxEPD2_3C.h>
#include <GxEPD2_BW.h>
#include <NimBLEDevice.h>
#include <WiFi.h>
// #include <ArduinoOTA.h>
#include <HTTPUpdateServer.h>
#include <WebServer.h>
#include "badge_config.h"
#if defined(BADGE_SSID_NAME) && defined(BADGE_SSID_PASS)
#define BADGE_USE_WIFI 1
#else
#define BADGE_USE_WIFI 0
#endif
NimBLEServer *server;
#if UVOK_EPAP_DISPLAY == DISPLAY_WAVESHARE_219_YBW
// HINT: Update the library code, set budy timeout to 30 or 60 seconds!
// Small color
GxEPD2_3C<GxEPD2_213_Z19c, GxEPD2_213_Z19c::HEIGHT> display(GxEPD2_213_Z19c(22, 21, 17, 16));
#elif UVOK_EPAP_DISPLAY == DISPLAY_WAVESHARE_290_BW
// larger b/w
// or T5
// GxEPD2_BW<GxEPD2_290_T5D, GxEPD2_290_T5D::HEIGHT> display(GxEPD2_290_T5D(22, 21, 17, 16));
GxEPD2_BW<GxEPD2_290_M06, GxEPD2_290_M06::HEIGHT> display(GxEPD2_290_M06(22, 21, 17, 16));
#elif UVOK_EPAP_DISPLAY == DISPLAY_ELECROW_290_BW
/*
#define SCK 12
#define MOSI 11
#define RES 47
#define DC 46
#define CS 45
#define BUSY 48
*/
GxEPD2_BW<GxEPD2_290_T94, GxEPD2_290_T94::HEIGHT> display(GxEPD2_290_T94(45, 46, 47, 48));
#else
#error "define display"
#endif
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
#define BUTTON_PIN 0
#define PRESS_TIME_DRAW 1000
#define PRESS_TIME_BLE_ADV 3000
#define SLEEP_TIME 10000
NimBLEAdvertising *pAdvertising;
WebServer httpServer(80);
HTTPUpdateServer httpUpdater;
void display_helloWorld();
void setup()
{
Serial.begin(115200);
Serial.println("Yes, it works!");
NimBLEDevice::init("Espadge");
server = NimBLEDevice::createServer();
NimBLEService *service = new NimBLEService("ca260000-b4bb-46b2-bd06-b7b7a61ea990");
auto c = service->createCharacteristic("ca260001-b4bb-46b2-bd06-b7b7a61ea990");
service->start();
c->setValue("1");
server->addService(service);
pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->setName("NimBLE");
Serial.println("Init display...");
#if UVOK_EPAP_DISPLAY == DISPLAY_ELECROW_290_BW
// Turn on once, let controller handle the rest, lest I want to do re-init...
pinMode(7, OUTPUT); // Set pin 7 as output mode
digitalWrite(7, HIGH); // Set pin 7 to high level to turn on the screen power
display.init(115200, true);
#else
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#endif
display.hibernate();
Serial.println("Display done.");
#if BADGE_USE_WIFI
WiFi.begin(BADGE_SSID_NAME, BADGE_SSID_PASS);
while (WiFi.status() != WL_CONNECTED)
delay(500);
Serial.printf("> My IP is %s\n", WiFi.localIP().toString());
httpUpdater.setup(&httpServer);
httpServer.begin();
#endif
// doesn't work as expected?
// gpio_wakeup_enable(GPIO_NUM_0, GPIO_INTR_LOW_LEVEL);
// esp_sleep_enable_gpio_wakeup();
// esp_light_sleep_start();
}
void loop()
{
#if BADGE_USE_WIFI
httpServer.handleClient();
#endif
static int lastState = HIGH;
int buttonState = digitalRead(BUTTON_PIN);
long pressDuration = 0;
if (lastState == HIGH && buttonState == LOW)
{
Serial.println("``\\__");
pressedTime = millis();
lastState = LOW;
}
else if (lastState == LOW && buttonState == HIGH)
{
lastState = HIGH;
Serial.println("__/``");
releasedTime = millis();
pressDuration = releasedTime - pressedTime;
};
if (pressDuration > PRESS_TIME_BLE_ADV)
{
if (!pAdvertising->isAdvertising())
{
Serial.println("Long press detected. Starting advertising...");
pAdvertising->start(10000);
}
}
else if (pressDuration > PRESS_TIME_DRAW)
{
Serial.println("Drawing...");
display_helloWorld();
}
// if (millis() - releasedTime > SLEEP_TIME && !pAdvertising->isAdvertising())
// {
// Serial.println("Go to sleep...");
// esp_light_sleep_start();
// }
}
#include "chee.c"
void display_helloWorld()
{
#define TEXT_BORDER 10
// display.clearScreen();
static const char s_hungry[] = "hungry";
display.setRotation(1);
display.setTextColor(GxEPD_BLACK);
int16_t tbx, tby;
uint16_t tbw, tbh;
display.setFont(&FreeMonoBold9pt7b);
display.getTextBounds(s_hungry, 0, 0, &tbx, &tby, &tbw, &tbh);
// center the bounding box by transposition of the origin:
uint16_t x = display.width() - tbw - TEXT_BORDER - tbx;
uint16_t y = ((display.height() - tbh) / 2) - tby;
display.setFullWindow();
display.firstPage();
do
{
display.drawXBitmap(0, 0, chee_bits, chee_width, chee_height, GxEPD_BLACK);
display.getTextBounds(s_hungry, x, y, &tbx, &tby, &tbw, &tbh);
display.fillRect(tbx - TEXT_BORDER, tby - TEXT_BORDER, tbw + 2 * TEXT_BORDER, tbh + 2 * TEXT_BORDER,
GxEPD_WHITE);
display.setCursor(x, y);
display.print(s_hungry);
} while (display.nextPage());
display.hibernate();
#undef TEXT_BORDER
}
|