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)
1039#include < Inkplate-LVGL.h>
1140#include < BluetoothSerial.h>
1241
13- // Promijeni po želji BT ime
1442static const char *btDeviceName = " Inkplate6" ;
1543
16- // Inkplate-LVGL (1-bit, parcijalni update friendly)
1744Inkplate inkplate (INKPLATE_1BIT);
1845BluetoothSerial 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 ------ ----
5352static 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-
7561static 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+
8394static 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
117155static 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
128167static 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
162214void 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);
0 commit comments