Skip to content

Commit fbfebfe

Browse files
committed
example update
1 parent 79d0bd2 commit fbfebfe

File tree

16 files changed

+1905
-0
lines changed

16 files changed

+1905
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/**
2+
**************************************************
3+
*
4+
* @file BluetoothSerial.ino
5+
* @brief Example showing how to use Bluetooth Serial on Inkplate 10
6+
* with an LVGL-based UI that safely renders incoming text.
7+
*
8+
* HOW TO USE
9+
* - Upload this example to Inkplate 10.
10+
* - Pair your phone with the device in Bluetooth settings (device name: "Inkplate10").
11+
* - Open a Serial Bluetooth Terminal app (or similar) and connect to "Inkplate10".
12+
* - Anything you type in the app will be shown on the Inkplate screen.
13+
* - Anything you type in the Arduino Serial Monitor will be sent to the phone.
14+
*
15+
*
16+
* For info on how to quickly get started with Inkplate 10 visit
17+
* https://soldered.com/documentation/inkplate/10/overview/
18+
*
19+
* @authors Soldered
20+
* @date November 2025
21+
**************************************************
22+
*/
23+
24+
#if !defined(ARDUINO_ESP32_DEV) && !defined(ARDUINO_INKPLATE10)
25+
#error "Wrong board selection for this example, please select e-radionica Inkplate10 or Soldered Inkplate10 in the boards menu."
26+
#endif
27+
28+
#include <Inkplate-LVGL.h>
29+
#include <BluetoothSerial.h>
30+
31+
static const char *btDeviceName = "Inkplate10";
32+
33+
Inkplate inkplate(INKPLATE_1BIT);
34+
BluetoothSerial SerialBT;
35+
36+
// ---------- Font helpers (use LV_FONT_DEFAULT only) ----------
37+
static const lv_font_t* font_big() { return LV_FONT_DEFAULT; }
38+
static const lv_font_t* font_small() { return LV_FONT_DEFAULT; }
39+
40+
// ---------- LVGL helpers ----------
41+
static inline int dispW() {
42+
lv_display_t *d = lv_display_get_default();
43+
return lv_display_get_horizontal_resolution(d);
44+
}
45+
static inline int dispH() {
46+
lv_display_t *d = lv_display_get_default();
47+
return lv_display_get_vertical_resolution(d);
48+
}
49+
50+
static int lineHeight(const lv_font_t *f) {
51+
#if LVGL_VERSION_MAJOR >= 9
52+
return lv_font_get_line_height(f);
53+
#else
54+
// Approximate default font line height for LVGL v8 if API is unavailable
55+
return 18;
56+
#endif
57+
}
58+
59+
static void make_opaque(lv_obj_t *obj) {
60+
lv_obj_set_style_bg_color(obj, lv_color_hex(0xFFFFFF), 0);
61+
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0);
62+
lv_obj_set_style_border_width(obj, 0, 0);
63+
}
64+
65+
// ---------- UI elements ----------
66+
static lv_obj_t *label_title = nullptr;
67+
static lv_obj_t *label_info = nullptr;
68+
static lv_obj_t *panel_log = nullptr;
69+
static lv_obj_t *label_log = nullptr;
70+
71+
// Spacing
72+
static const int INFO_LINE_SPACE = 4;
73+
static const int LOG_LINE_SPACE = 6;
74+
static const int topMargin = 8;
75+
static const int leftMargin = 8;
76+
static const int rightMargin = 8;
77+
78+
// Log state
79+
static String logText;
80+
static int maxLines = 0;
81+
static int usedLines = 0;
82+
83+
static void ui_create() {
84+
// Screen background
85+
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0xFFFFFF), LV_PART_MAIN);
86+
87+
// Title
88+
label_title = lv_label_create(lv_screen_active());
89+
lv_obj_set_style_text_color(label_title, lv_color_hex(0x000000), 0);
90+
lv_obj_set_style_text_font(label_title, font_big(), 0);
91+
lv_label_set_text(label_title, "Bluetooth Serial Example");
92+
lv_obj_set_pos(label_title, leftMargin, topMargin);
93+
make_opaque(label_title);
94+
95+
// Instructions
96+
label_info = lv_label_create(lv_screen_active());
97+
lv_obj_set_style_text_color(label_info, lv_color_hex(0x000000), 0);
98+
lv_obj_set_style_text_font(label_info, font_small(), 0);
99+
lv_label_set_long_mode(label_info, LV_LABEL_LONG_WRAP);
100+
lv_obj_set_style_text_line_space(label_info, INFO_LINE_SPACE, 0);
101+
int infoY = topMargin + lineHeight(font_big()) + 8;
102+
lv_obj_set_pos(label_info, leftMargin, infoY);
103+
lv_obj_set_width(label_info, dispW() - leftMargin - rightMargin);
104+
lv_label_set_text(label_info,
105+
"Pair your phone and open a Serial Bluetooth Terminal.\n"
106+
"Messages from phone appear below.\n"
107+
"USB Serial -> phone is also forwarded.\n");
108+
make_opaque(label_info);
109+
110+
// Ensure layout is computed before measuring info height
111+
lv_timer_handler();
112+
#if LVGL_VERSION_MAJOR >= 9
113+
lv_obj_update_layout(label_info);
114+
#endif
115+
int infoBottom = lv_obj_get_y(label_info) + lv_obj_get_height(label_info);
116+
117+
// Opaque log panel below the instructions
118+
panel_log = lv_obj_create(lv_screen_active());
119+
make_opaque(panel_log);
120+
lv_obj_set_style_pad_all(panel_log, 0, 0);
121+
lv_obj_set_style_border_width(panel_log, 0, 0);
122+
int panelX = leftMargin;
123+
int panelY = infoBottom + 10;
124+
int panelW = dispW() - leftMargin - rightMargin;
125+
int panelH = dispH() - panelY - topMargin;
126+
lv_obj_set_pos(panel_log, panelX, panelY);
127+
lv_obj_set_size(panel_log, panelW, panelH);
128+
129+
// Log label inside the panel
130+
label_log = lv_label_create(panel_log);
131+
lv_obj_set_style_text_color(label_log, lv_color_hex(0x000000), 0);
132+
lv_obj_set_style_text_font(label_log, font_small(), 0);
133+
lv_label_set_long_mode(label_log, LV_LABEL_LONG_WRAP);
134+
lv_obj_set_style_text_line_space(label_log, LOG_LINE_SPACE, 0);
135+
lv_obj_set_pos(label_log, 0, 0);
136+
lv_obj_set_width(label_log, panelW);
137+
138+
// Compute how many lines fit into the panel
139+
int effLineH = lineHeight(font_small()) + LOG_LINE_SPACE;
140+
maxLines = (effLineH > 0) ? (panelH / effLineH) : 0;
141+
if (maxLines < 3) maxLines = 3; // safety minimum
142+
}
143+
144+
static void ui_reset_log_full_refresh() {
145+
// Rebuild the entire UI and perform a full refresh (avoids ghosting)
146+
lv_obj_clean(lv_screen_active());
147+
logText = "";
148+
usedLines = 0;
149+
ui_create();
150+
151+
lv_tick_inc(10);
152+
lv_timer_handler();
153+
inkplate.display(); // FULL
154+
}
155+
156+
static void log_append_char(char c) {
157+
if (c == '\r') return;
158+
159+
if (c == '\n') {
160+
logText += '\n';
161+
usedLines++;
162+
} else {
163+
logText += c;
164+
}
165+
166+
if (usedLines >= maxLines) {
167+
ui_reset_log_full_refresh();
168+
return;
169+
}
170+
171+
lv_label_set_text(label_log, logText.c_str());
172+
173+
// Partial refresh for faster updates; opaque panel removes old pixels
174+
lv_tick_inc(5);
175+
lv_timer_handler();
176+
inkplate.partialUpdate();
177+
}
178+
179+
void setup() {
180+
Serial.begin(115200);
181+
inkplate.begin(LV_DISP_RENDER_MODE_PARTIAL);
182+
183+
ui_create();
184+
185+
// Initial full refresh to clear any boot artifacts
186+
lv_tick_inc(20);
187+
lv_timer_handler();
188+
inkplate.display();
189+
190+
// Start Bluetooth
191+
if (!SerialBT.begin(btDeviceName)) {
192+
const char *err = "Bluetooth init ERROR";
193+
for (const char *p = err; *p; ++p) log_append_char(*p);
194+
log_append_char('\n');
195+
} else {
196+
const char *ok1 = "BT ready. Pair and connect.";
197+
for (const char *p = ok1; *p; ++p) log_append_char(*p);
198+
log_append_char('\n');
199+
log_append_char('\n'); // extra spacing before user messages
200+
}
201+
}
202+
203+
void loop() {
204+
// USB Serial -> Bluetooth
205+
while (Serial.available()) {
206+
char c = (char)Serial.read();
207+
SerialBT.write((uint8_t)c);
208+
}
209+
210+
// Bluetooth -> screen + echo to USB Serial
211+
while (SerialBT.available()) {
212+
char c = (char)SerialBT.read();
213+
Serial.write((uint8_t)c);
214+
log_append_char(c);
215+
}
216+
217+
lv_tick_inc(5);
218+
lv_timer_handler();
219+
delay(20);
220+
}

examples/Inkplate10/Advanced/Communication/Qwiic/Qwiic.ino renamed to examples/Inkplate10/Advanced/Communications/Qwiic/Qwiic.ino

File renamed without changes.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
**************************************************
3+
*
4+
* @file ExternalExpander.ino
5+
* @brief Example showing how to set up the external IO expander to blink an LED
6+
* on Inkplate 10 using the Inkplate-LVGL library.
7+
*
8+
* For info on how to quickly get started with Inkplate 10 visit:
9+
* https://soldered.com/documentation/inkplate/10/overview/
10+
*
11+
* Connect a 330 Ohm resistor and an LED to pin P1-7 (GPB7) on the "IO Expander 2" header:
12+
* - P1-7 (GPB7) -> 330 Ohm resistor -> LED anode (+)
13+
* - LED cathode (-) -> GND
14+
*
15+
* On this expander all pins are free to use by default. Nothing is connected internally.
16+
*
17+
* Pin mapping on the external IO expander:
18+
* - GPA0 = 0, GPA1 = 1, ..., GPA7 = 7
19+
* - GPB0 = 8, GPB1 = 9, ..., GPB7 = 15
20+
* - P0-0 = GPA0, P0-1 = GPA1, ..., P0-7 = GPA7
21+
* - P1-0 = GPB0, P1-1 = GPB1, ..., P1-7 = GPB7
22+
*
23+
* In this example we use P1-7 = GPB7 = pin 15.
24+
*
25+
* LVGL is initialized in PARTIAL render mode. The display backend is configured
26+
* for L8 (8-bit grayscale) in the Inkplate-LVGL configuration.
27+
*
28+
* @authors Soldered
29+
* @date November 2025
30+
***************************************************/
31+
32+
// Board selection safety check (supports Inkplate 10 and Inkplate 10 V2)
33+
#if !defined(ARDUINO_INKPLATE10) && !defined(ARDUINO_INKPLATE10V2)
34+
#error "Wrong board selection for this example, please select e-radionica Inkplate10 or Soldered Inkplate10 in the boards menu."
35+
#endif
36+
37+
// Include the Inkplate LVGL library
38+
#include "Inkplate-LVGL.h"
39+
40+
// We are going to use pin P1-7 (or GPB7 on older Inkplates).
41+
// P1-7 = GPB7 = 15 in the external IO expander index.
42+
#define LED_PIN 15
43+
44+
// Create an instance of the Inkplate object
45+
Inkplate display;
46+
47+
void setup()
48+
{
49+
Serial.begin(115200);
50+
delay(1000);
51+
Serial.println("External IO Expander LED blink on Inkplate 10 (LVGL / L8 backend)");
52+
53+
// Init Inkplate library and LVGL in PARTIAL render mode
54+
display.begin(LV_DISP_RENDER_MODE_PARTIAL);
55+
56+
// Set LED pin (P1-7 / GPB7 / 15) as output on the external IO expander
57+
display.externalIO.pinMode(LED_PIN, OUTPUT);
58+
}
59+
60+
void loop()
61+
{
62+
// Turn LED off (set output LOW)
63+
display.externalIO.digitalWrite(LED_PIN, LOW);
64+
delay(1000); // Wait for one second
65+
66+
// Turn LED on (set output HIGH)
67+
display.externalIO.digitalWrite(LED_PIN, HIGH);
68+
delay(1000); // Wait for one second
69+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
**************************************************
3+
*
4+
* @file InternalExpander.ino
5+
* @brief Example showing how to use the *internal* IO expander on Inkplate 10
6+
* to blink an LED on pin P1-7 (GPB7).
7+
*
8+
* For info on how to quickly get started with Inkplate 10 visit:
9+
* https://soldered.com/documentation/inkplate/10/overview/
10+
*
11+
* For this example you will need:
12+
* - Inkplate 10
13+
* - Micro USB cable
14+
* - 330 Ohm resistor
15+
* - LED diode
16+
*
17+
* Hardware connection (INTERNAL IO EXPANDER, "IO Expander 1" header at the top):
18+
* - Connect 330 Ohm resistor to P1-7 (GPB7)
19+
* - Other side of resistor -> LED anode (+)
20+
* - LED cathode (-) -> GND
21+
*
22+
* This example shows how to manipulate I/Os of the *internal* IO expander.
23+
*
24+
* You can only freely use Port B pins P1-1 -> P1-7 (GPB1 -> GPB7) on the internal expander.
25+
* Port A (P0-0 -> P0-7 / GPA0 -> GPA7) is used for the epaper panel and TPS65186 PMIC.
26+
* P1-0 (GPB0) is used for ESP32 GPIO0 and must not be used as a general-purpose pin.
27+
*
28+
* IMPORTANT (DANGER):
29+
* - DO NOT USE P0-0 -> P0-7 (GPA0 -> GPA7) or P1-0 (GPB0) on the internal expander.
30+
* - In code those are pins 0–8.
31+
* - You should only use pins 9–15 on the internal expander.
32+
* - Using the wrong pins may permanently damage the screen.
33+
*
34+
* Pin mapping on the IO expander:
35+
* - GPA0 = 0, GPA1 = 1, ..., GPA7 = 7
36+
* - GPB0 = 8, GPB1 = 9, ..., GPB7 = 15
37+
* - P0-0 = GPA0, P0-1 = GPA1, ..., P0-7 = GPA7
38+
* - P1-0 = GPB0, P1-1 = GPB1, ..., P1-7 = GPB7
39+
*
40+
* In this example we use P1-7 = GPB7 = 15 on the *internal* IO expander.
41+
*
42+
* LVGL is initialized in PARTIAL render mode. The display backend is configured
43+
* for L8 (8-bit grayscale) in the Inkplate-LVGL configuration.
44+
*
45+
* @authors Soldered
46+
* @date November 2025
47+
***************************************************/
48+
49+
// Board selection safety check (supports Inkplate 10 and Inkplate 10 V2)
50+
#if !defined(ARDUINO_INKPLATE10) && !defined(ARDUINO_INKPLATE10V2)
51+
#error "Wrong board selection for this example, please select e-radionica Inkplate10 or Soldered Inkplate10 in the boards menu."
52+
#endif
53+
54+
// Include the Inkplate LVGL Library
55+
#include "Inkplate-LVGL.h"
56+
57+
// We are going to use pin P1-7 (or GPB7).
58+
// P1-7 = GPB7 = 15 in the IO expander index.
59+
#define LED_PIN 15
60+
61+
// Create an instance of the Inkplate object
62+
Inkplate display;
63+
64+
void setup()
65+
{
66+
Serial.begin(115200);
67+
delay(1000);
68+
Serial.println("Internal IO Expander LED blink on Inkplate 10 (LVGL / L8 backend)");
69+
70+
// Init Inkplate library and LVGL in PARTIAL render mode
71+
display.begin(LV_DISP_RENDER_MODE_PARTIAL);
72+
73+
// Set P1-7 (GPB7) as output on the *internal* IO expander
74+
// Only pins 9–15 are safe to use on the internal expander.
75+
display.internalIO.pinMode(LED_PIN, OUTPUT);
76+
}
77+
78+
void loop()
79+
{
80+
// Set output to LOW (LED off)
81+
display.internalIO.digitalWrite(LED_PIN, LOW);
82+
delay(1000); // Wait for one second
83+
84+
// Set output to HIGH (LED on)
85+
display.internalIO.digitalWrite(LED_PIN, HIGH);
86+
delay(1000); // Wait for one second
87+
}

0 commit comments

Comments
 (0)