Skip to content

Commit ee92b2a

Browse files
committed
progress update
1 parent 95e3ab4 commit ee92b2a

File tree

4 files changed

+181
-75
lines changed

4 files changed

+181
-75
lines changed

examples/Inkplate6/Advanced/Communications/BluetoothSerial/BluetoothSerial.ino

Lines changed: 121 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
1+
/**
2+
**************************************************
3+
*
4+
* @file BluetoothSerial.ino
5+
* @brief Example showing how to use Bluetooth Serial on Inkplate 6
6+
* with an LVGL-based UI that safely renders incoming text.
7+
*
8+
* HOW TO USE
9+
* - Upload this example to Inkplate 6.
10+
* - Pair your phone with the device in Bluetooth settings (device name: "Inkplate6").
11+
* - Open a Serial Bluetooth Terminal app (or similar) and connect to "Inkplate6".
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+
* NOTES
16+
* - Runs in 1-bit mode for fast partial updates.
17+
* - A dedicated opaque "log panel" prevents ghosting/overlap with the header.
18+
* - Uses LV_FONT_DEFAULT to work out-of-the-box without extra fonts.
19+
*
20+
* Learn more about Inkplate: https://www.inkplate.io
21+
* Support forum: https://forum.soldered.com/
22+
*
23+
* @authors Soldered
24+
* @date November 2025
25+
**************************************************
26+
*/
27+
128
/*
2-
Inkplate6 — Bluetooth Serial (LVGL verzija) — font-safe
3-
Automatski bira dostupne Montserrat fontove iz lv_conf.h
29+
Inkplate6 — Bluetooth Serial (LVGL) — safe layout with default font
30+
- Forces LVGL layout before measuring sizes (prevents overlap)
31+
- Uses an opaque white log panel below the instructions
32+
- Adds line spacing; partial updates only touch the log panel
433
*/
534

635
#if !defined(ARDUINO_ESP32_DEV) && !defined(ARDUINO_INKPLATE6V2)
@@ -10,46 +39,16 @@
1039
#include <Inkplate-LVGL.h>
1140
#include <BluetoothSerial.h>
1241

13-
// Promijeni po želji BT ime
1442
static const char *btDeviceName = "Inkplate6";
1543

16-
// Inkplate-LVGL (1-bit, parcijalni update friendly)
1744
Inkplate inkplate(INKPLATE_1BIT);
1845
BluetoothSerial SerialBT;
1946

20-
// ---------------- Font helperi (biraju prvi dostupni) ----------------
21-
static const lv_font_t* font_big() {
22-
// prefer: 36, 32, 28, 26, 24
23-
#if LV_FONT_MONTSERRAT_36
24-
return &lv_font_montserrat_36;
25-
#elif LV_FONT_MONTSERRAT_32
26-
return &lv_font_montserrat_32;
27-
#elif LV_FONT_MONTSERRAT_28
28-
return &lv_font_montserrat_28;
29-
#elif LV_FONT_MONTSERRAT_26
30-
return &lv_font_montserrat_26;
31-
#elif LV_FONT_MONTSERRAT_24
32-
return &lv_font_montserrat_24;
33-
#else
34-
return LV_FONT_DEFAULT;
35-
#endif
36-
}
37-
static const lv_font_t* font_small() {
38-
// prefer: 20, 18, 16, 14
39-
#if LV_FONT_MONTSERRAT_20
40-
return &lv_font_montserrat_20;
41-
#elif LV_FONT_MONTSERRAT_18
42-
return &lv_font_montserrat_18;
43-
#elif LV_FONT_MONTSERRAT_16
44-
return &lv_font_montserrat_16;
45-
#elif LV_FONT_MONTSERRAT_14
46-
return &lv_font_montserrat_14;
47-
#else
48-
return LV_FONT_DEFAULT;
49-
#endif
50-
}
47+
// ---------- Font helpers (use LV_FONT_DEFAULT only) ----------
48+
static const lv_font_t* font_big() { return LV_FONT_DEFAULT; }
49+
static const lv_font_t* font_small() { return LV_FONT_DEFAULT; }
5150

52-
// ---- LVGL pomoćne stvari ----
51+
// ---------- LVGL helpers ----------
5352
static inline int dispW() {
5453
lv_display_t *d = lv_display_get_default();
5554
return lv_display_get_horizontal_resolution(d);
@@ -59,62 +58,102 @@ static inline int dispH() {
5958
return lv_display_get_vertical_resolution(d);
6059
}
6160

62-
// UI elementi
63-
static lv_obj_t *label_title = nullptr;
64-
static lv_obj_t *label_info = nullptr;
65-
static lv_obj_t *label_log = nullptr;
66-
67-
// Log state
68-
static String logText;
69-
static int maxLines = 0;
70-
static int usedLines = 0;
71-
static int topMargin = 8;
72-
static int leftMargin = 8;
73-
static int logY = 0;
74-
7561
static int lineHeight(const lv_font_t *f) {
7662
#if LVGL_VERSION_MAJOR >= 9
7763
return lv_font_get_line_height(f);
7864
#else
79-
return 20; // približno za manje fontove
65+
// Approximate default font line height for LVGL v8 if API is unavailable
66+
return 18;
8067
#endif
8168
}
8269

70+
static void make_opaque(lv_obj_t *obj) {
71+
lv_obj_set_style_bg_color(obj, lv_color_hex(0xFFFFFF), 0);
72+
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0);
73+
lv_obj_set_style_border_width(obj, 0, 0);
74+
}
75+
76+
// ---------- UI elements ----------
77+
static lv_obj_t *label_title = nullptr;
78+
static lv_obj_t *label_info = nullptr;
79+
static lv_obj_t *panel_log = nullptr;
80+
static lv_obj_t *label_log = nullptr;
81+
82+
// Spacing
83+
static const int INFO_LINE_SPACE = 4;
84+
static const int LOG_LINE_SPACE = 6;
85+
static const int topMargin = 8;
86+
static const int leftMargin = 8;
87+
static const int rightMargin = 8;
88+
89+
// Log state
90+
static String logText;
91+
static int maxLines = 0;
92+
static int usedLines = 0;
93+
8394
static void ui_create() {
95+
// Screen background
8496
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0xFFFFFF), LV_PART_MAIN);
8597

98+
// Title
8699
label_title = lv_label_create(lv_screen_active());
87100
lv_obj_set_style_text_color(label_title, lv_color_hex(0x000000), 0);
88101
lv_obj_set_style_text_font(label_title, font_big(), 0);
89102
lv_label_set_text(label_title, "Bluetooth Serial Example");
90103
lv_obj_set_pos(label_title, leftMargin, topMargin);
104+
make_opaque(label_title);
91105

106+
// Instructions
92107
label_info = lv_label_create(lv_screen_active());
93108
lv_obj_set_style_text_color(label_info, lv_color_hex(0x000000), 0);
94109
lv_obj_set_style_text_font(label_info, font_small(), 0);
95110
lv_label_set_long_mode(label_info, LV_LABEL_LONG_WRAP);
96-
int infoY = topMargin + lineHeight(font_big()) + 6;
111+
lv_obj_set_style_text_line_space(label_info, INFO_LINE_SPACE, 0);
112+
int infoY = topMargin + lineHeight(font_big()) + 8;
97113
lv_obj_set_pos(label_info, leftMargin, infoY);
98-
lv_obj_set_width(label_info, dispW() - 2*leftMargin);
114+
lv_obj_set_width(label_info, dispW() - leftMargin - rightMargin);
99115
lv_label_set_text(label_info,
100-
"Pair your phone and open a serial BT terminal.\n"
101-
"Messages from phone appear here.\n"
116+
"Pair your phone and open a Serial Bluetooth Terminal.\n"
117+
"Messages from phone appear below.\n"
102118
"USB Serial -> phone is also forwarded.\n");
119+
make_opaque(label_info);
103120

104-
label_log = lv_label_create(lv_screen_active());
121+
// Ensure layout is computed before measuring info height
122+
lv_timer_handler();
123+
#if LVGL_VERSION_MAJOR >= 9
124+
lv_obj_update_layout(label_info);
125+
#endif
126+
int infoBottom = lv_obj_get_y(label_info) + lv_obj_get_height(label_info);
127+
128+
// Opaque log panel below the instructions
129+
panel_log = lv_obj_create(lv_screen_active());
130+
make_opaque(panel_log);
131+
lv_obj_set_style_pad_all(panel_log, 0, 0);
132+
lv_obj_set_style_border_width(panel_log, 0, 0);
133+
int panelX = leftMargin;
134+
int panelY = infoBottom + 10;
135+
int panelW = dispW() - leftMargin - rightMargin;
136+
int panelH = dispH() - panelY - topMargin;
137+
lv_obj_set_pos(panel_log, panelX, panelY);
138+
lv_obj_set_size(panel_log, panelW, panelH);
139+
140+
// Log label inside the panel
141+
label_log = lv_label_create(panel_log);
105142
lv_obj_set_style_text_color(label_log, lv_color_hex(0x000000), 0);
106143
lv_obj_set_style_text_font(label_log, font_small(), 0);
107144
lv_label_set_long_mode(label_log, LV_LABEL_LONG_WRAP);
108-
logY = infoY + lv_obj_get_height(label_info) + 8;
109-
lv_obj_set_pos(label_log, leftMargin, logY);
110-
lv_obj_set_width(label_log, dispW() - 2*leftMargin);
111-
112-
int availH = dispH() - logY - topMargin;
113-
maxLines = availH / lineHeight(font_small());
114-
if (maxLines < 3) maxLines = 3;
145+
lv_obj_set_style_text_line_space(label_log, LOG_LINE_SPACE, 0);
146+
lv_obj_set_pos(label_log, 0, 0);
147+
lv_obj_set_width(label_log, panelW);
148+
149+
// Compute how many lines fit into the panel
150+
int effLineH = lineHeight(font_small()) + LOG_LINE_SPACE;
151+
maxLines = (effLineH > 0) ? (panelH / effLineH) : 0;
152+
if (maxLines < 3) maxLines = 3; // safety minimum
115153
}
116154

117155
static void ui_reset_log_full_refresh() {
156+
// Rebuild the entire UI and perform a full refresh (avoids ghosting)
118157
lv_obj_clean(lv_screen_active());
119158
logText = "";
120159
usedLines = 0;
@@ -127,12 +166,22 @@ static void ui_reset_log_full_refresh() {
127166

128167
static void log_append_char(char c) {
129168
if (c == '\r') return;
130-
if (c == '\n') { logText += '\n'; usedLines++; }
131-
else { logText += c; }
132169

133-
if (usedLines >= maxLines) { ui_reset_log_full_refresh(); return; }
170+
if (c == '\n') {
171+
logText += '\n';
172+
usedLines++;
173+
} else {
174+
logText += c;
175+
}
176+
177+
if (usedLines >= maxLines) {
178+
ui_reset_log_full_refresh();
179+
return;
180+
}
134181

135182
lv_label_set_text(label_log, logText.c_str());
183+
184+
// Partial refresh for faster updates; opaque panel removes old pixels
136185
lv_tick_inc(5);
137186
lv_timer_handler();
138187
inkplate.partialUpdate();
@@ -143,11 +192,13 @@ void setup() {
143192
inkplate.begin(LV_DISP_RENDER_MODE_PARTIAL);
144193

145194
ui_create();
195+
196+
// Initial full refresh to clear any boot artifacts
146197
lv_tick_inc(20);
147198
lv_timer_handler();
148-
inkplate.display(); // prvi FULL
199+
inkplate.display();
149200

150-
// Bluetooth
201+
// Start Bluetooth
151202
if (!SerialBT.begin(btDeviceName)) {
152203
const char *err = "Bluetooth init ERROR";
153204
for (const char *p = err; *p; ++p) log_append_char(*p);
@@ -156,15 +207,18 @@ void setup() {
156207
const char *ok1 = "BT ready. Pair and connect.";
157208
for (const char *p = ok1; *p; ++p) log_append_char(*p);
158209
log_append_char('\n');
210+
log_append_char('\n'); // extra spacing before user messages
159211
}
160212
}
161213

162214
void loop() {
215+
// USB Serial -> Bluetooth
163216
while (Serial.available()) {
164217
char c = (char)Serial.read();
165218
SerialBT.write((uint8_t)c);
166219
}
167220

221+
// Bluetooth -> screen + echo to USB Serial
168222
while (SerialBT.available()) {
169223
char c = (char)SerialBT.read();
170224
Serial.write((uint8_t)c);

examples/Inkplate6/Basic/BlackAndWhite/BlackAndWhite.ino

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
// Inkplate 6 + LVGL — Black & White demo
2-
// Jednostavna podjela ekrana na crni i bijeli blok (1-bit mod)
1+
/**
2+
**************************************************
3+
*
4+
* @file BlackWhite.ino
5+
* @brief Example showing a simple black & white screen split using LVGL on Inkplate 6
6+
*
7+
* For info on how to quickly get started with Inkplate 6 visit https://soldered.com/documentation/inkplate/6/overview/
8+
*
9+
* @authors Soldered
10+
* @date November 2025
11+
**************************************************
12+
*/
313

414
#include <Inkplate-LVGL.h>
515

16+
// Create Inkplate instance in 1-bit (black & white) mode
617
Inkplate inkplate(INKPLATE_1BIT);
718

19+
// Helper functions to get current display width and height from LVGL
820
static inline int dispW() {
921
lv_display_t *d = lv_display_get_default();
1022
return lv_display_get_horizontal_resolution(d);
@@ -14,18 +26,21 @@ static inline int dispH() {
1426
return lv_display_get_vertical_resolution(d);
1527
}
1628

29+
// Draws the screen divided into black and white halves
1730
void drawBlackWhite() {
1831
int w = dispW();
1932
int h = dispH();
2033
int half = w / 2;
2134

35+
// Left half — black rectangle
2236
lv_obj_t *left = lv_obj_create(lv_screen_active());
2337
lv_obj_remove_flag(left, LV_OBJ_FLAG_SCROLLABLE);
2438
lv_obj_set_size(left, half, h);
2539
lv_obj_set_pos(left, 0, 0);
2640
lv_obj_set_style_border_width(left, 0, LV_PART_MAIN);
2741
lv_obj_set_style_bg_color(left, lv_color_hex(0x000000), LV_PART_MAIN);
2842

43+
// Right half — white rectangle
2944
lv_obj_t *right = lv_obj_create(lv_screen_active());
3045
lv_obj_remove_flag(right, LV_OBJ_FLAG_SCROLLABLE);
3146
lv_obj_set_size(right, w - half, h);
@@ -35,15 +50,20 @@ void drawBlackWhite() {
3550
}
3651

3752
void setup() {
53+
// Initialize Inkplate and LVGL in FULL render mode
3854
inkplate.begin(LV_DISP_RENDER_MODE_FULL);
3955
inkplate.selectDisplayMode(INKPLATE_1BIT);
4056

57+
// Set white background and draw both halves
4158
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0xFFFFFF), LV_PART_MAIN);
4259
drawBlackWhite();
4360

61+
// Update LVGL and display the rendered frame
4462
lv_tick_inc(50);
4563
lv_timer_handler();
4664
inkplate.display();
4765
}
4866

49-
void loop() {}
67+
void loop() {
68+
// Nothing to do here; image is static
69+
}

0 commit comments

Comments
 (0)