Browse Source

first text rendering test

Thomas Buck 10 months ago
parent
commit
6a4c2b8e16
13 changed files with 309 additions and 27 deletions
  1. 2
    0
      CMakeLists.txt
  2. 1
    1
      debug.sh
  3. 24
    0
      include/image.h
  4. 1
    0
      include/lcd.h
  5. 1
    0
      include/log.h
  6. 47
    0
      include/text.h
  7. 59
    0
      src/console.c
  8. 43
    0
      src/image.c
  9. 4
    2
      src/lcd.c
  10. 0
    1
      src/log.c
  11. 12
    23
      src/main.c
  12. 112
    0
      src/text.c
  13. 3
    0
      src/util.c

+ 2
- 0
CMakeLists.txt View File

@@ -57,6 +57,8 @@ target_sources(gadget PUBLIC
57 57
     src/lipo.c
58 58
     src/ble.c
59 59
     src/lcd.c
60
+    src/text.c
61
+    src/image.c
60 62
 
61 63
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
62 64
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c

+ 1
- 1
debug.sh View File

@@ -15,4 +15,4 @@ echo Opening picocom terminal
15 15
 echo "[C-a] [C-x] to exit"
16 16
 echo
17 17
 
18
-picocom -q --omap crcrlf $SERIAL
18
+picocom -q --omap crcrlf --imap lfcrlf $SERIAL

+ 24
- 0
include/image.h View File

@@ -0,0 +1,24 @@
1
+/*
2
+ * image.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __IMAGE_H__
20
+#define __IMAGE_H__
21
+
22
+void draw_splash(void);
23
+
24
+#endif // __IMAGE_H__

+ 1
- 0
include/lcd.h View File

@@ -24,6 +24,7 @@ void lcd_init(void);
24 24
 uint16_t lcd_get_backlight(void);
25 25
 void lcd_set_backlight(uint16_t value);
26 26
 
27
+void lcd_clear(void);
27 28
 void lcd_write_point(uint16_t x, uint16_t y, uint32_t color);
28 29
 
29 30
 #endif // __LCD_H__

+ 1
- 0
include/log.h View File

@@ -21,6 +21,7 @@
21 21
 
22 22
 #include <stdarg.h>
23 23
 #include <stdbool.h>
24
+#include "pico/stdlib.h"
24 25
 
25 26
 // for output that is stored in the debug log.
26 27
 // will be re-played from buffer when terminal connects

+ 47
- 0
include/text.h View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * text.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __TEXT_H__
20
+#define __TEXT_H__
21
+
22
+#include "mcufont.h"
23
+
24
+struct text_font {
25
+    const char *fontname;
26
+    //int scale; // TODO not supported - requires somewhere to store scaled versions
27
+
28
+    const struct mf_font_s *font;
29
+};
30
+
31
+struct text_conf {
32
+    const char *text;
33
+    int x;
34
+    int y;
35
+    bool justify;
36
+    enum mf_align_t alignment;
37
+    int width;
38
+    int height;
39
+    int margin;
40
+
41
+    struct text_font *font;
42
+};
43
+
44
+void text_prepare_font(struct text_font *tf);
45
+void text_draw(struct text_conf *tc);
46
+
47
+#endif // __TEXT_H__

+ 59
- 0
src/console.c View File

@@ -30,6 +30,9 @@
30 30
 #include "console.h"
31 31
 #include "lipo.h"
32 32
 #include "ble.h"
33
+#include "text.h"
34
+#include "lcd.h"
35
+#include "image.h"
33 36
 
34 37
 #define CNSL_BUFF_SIZE 1024
35 38
 #define CNSL_REPEAT_MS 500
@@ -75,6 +78,10 @@ static void cnsl_interpret(const char *line) {
75 78
         println("  mount - make mass storage medium (un)available");
76 79
         println("  power - show Lipo battery status");
77 80
         println("   scan - start or stop BLE scan");
81
+        println("  clear - blank screen");
82
+        println(" splash - draw image on screen");
83
+        println("  fonts - show font list");
84
+        println("   text - draw text on screen");
78 85
         println("Press Enter with no input to repeat last command.");
79 86
         println("Use repeat to continuously execute last command.");
80 87
         println("Stop this by calling repeat again.");
@@ -93,6 +100,58 @@ static void cnsl_interpret(const char *line) {
93 100
                 lipo_charging() ? "charging" : "draining");
94 101
     } else if (strcmp(line, "scan") == 0) {
95 102
         ble_scan(2);
103
+    } else if (strcmp(line, "clear") == 0) {
104
+        lcd_clear();
105
+    } else if (strcmp(line, "splash") == 0) {
106
+        draw_splash();
107
+    } else if (strcmp(line, "fonts") == 0) {
108
+        const struct mf_font_list_s *f = mf_get_font_list();
109
+
110
+        debug("Font list:");
111
+        while (f) {
112
+            debug("full_name: %s", f->font->full_name);
113
+            debug("short_name: %s", f->font->short_name);
114
+            debug("size: %d %d", f->font->width, f->font->height);
115
+            debug("x_advance: %d %d", f->font->min_x_advance, f->font->max_x_advance);
116
+            debug("baseline: %d %d", f->font->baseline_x, f->font->baseline_y);
117
+            debug("line_height: %d", f->font->line_height);
118
+            debug("flags: %d", f->font->flags);
119
+            debug("fallback_character: %c", f->font->fallback_character);
120
+            debug("character_width: %p", f->font->character_width);
121
+            debug("render_character: %p", f->font->render_character);
122
+
123
+            f = f->next;
124
+            if (f) {
125
+                debug("");
126
+            }
127
+        }
128
+    } else if (strcmp(line, "text") == 0) {
129
+        uint16_t y_off = 0;
130
+        const struct mf_font_list_s *f = mf_get_font_list();
131
+        while (f) {
132
+            struct text_font font = {
133
+                .fontname = f->font->short_name,
134
+                //.scale = 1,
135
+                .font = f->font,
136
+            };
137
+            text_prepare_font(&font);
138
+
139
+            struct text_conf text = {
140
+                .text = font.fontname,
141
+                .x = 0,
142
+                .y = y_off,
143
+                .justify = false,
144
+                .alignment = MF_ALIGN_CENTER,
145
+                .width = 240,
146
+                .height = 240 - y_off,
147
+                .margin = 5,
148
+                .font = &font,
149
+            };
150
+            text_draw(&text);
151
+
152
+            y_off = text.y;
153
+            f = f->next;
154
+        }
96 155
     } else {
97 156
         println("unknown command \"%s\"", line);
98 157
     }

+ 43
- 0
src/image.c View File

@@ -0,0 +1,43 @@
1
+/*
2
+ * image.c
3
+ *
4
+ * Copyright (c) 2022 - 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include "pico/stdlib.h"
20
+
21
+#include "config.h"
22
+#include "lcd.h"
23
+#include "image.h"
24
+
25
+#pragma GCC diagnostic push
26
+#pragma GCC diagnostic ignored "-Wtrigraphs"
27
+#include "logo.h"
28
+#pragma GCC diagnostic pop
29
+
30
+void draw_splash(void) {
31
+    char *data = logo_rgb_data;
32
+    for (uint x = 0; x < logo_width; x++) {
33
+        for (uint y = 0; y < logo_height; y++) {
34
+            uint32_t pixel[3];
35
+            HEADER_PIXEL(data, pixel);
36
+
37
+            uint32_t color = (pixel[0] >> 3) << 11;
38
+            color |= (pixel[1] >> 2) << 5;
39
+            color |= pixel[2] >> 3;
40
+            lcd_write_point(240 - x - 1, y, color);
41
+        }
42
+    }
43
+}

+ 4
- 2
src/lcd.c View File

@@ -262,8 +262,10 @@ void lcd_set_backlight(uint16_t value) {
262 262
     pwm_set_chan_level(bl_slice, bl_channel, bl_value);
263 263
 }
264 264
 
265
+void lcd_clear(void) {
266
+    st7789_clear(&gs_handle);
267
+}
268
+
265 269
 void lcd_write_point(uint16_t x, uint16_t y, uint32_t color) {
266 270
     st7789_draw_point(&gs_handle, x, y, color);
267
-
268
-    st7789_display_on(&gs_handle);
269 271
 }

+ 0
- 1
src/log.c View File

@@ -18,7 +18,6 @@
18 18
 
19 19
 #include <stdio.h>
20 20
 
21
-#include "pico/stdlib.h"
22 21
 #include "hardware/watchdog.h"
23 22
 #include "ff.h"
24 23
 

+ 12
- 23
src/main.c View File

@@ -30,43 +30,28 @@
30 30
 #include "buttons.h"
31 31
 #include "ble.h"
32 32
 #include "lcd.h"
33
-
34
-#pragma GCC diagnostic push
35
-#pragma GCC diagnostic ignored "-Wtrigraphs"
36
-#include "logo.h"
37
-#pragma GCC diagnostic pop
38
-
39
-static void draw_splash(void) {
40
-    char *data = logo_rgb_data;
41
-    for (uint x = 0; x < logo_width; x++) {
42
-        for (uint y = 0; y < logo_height; y++) {
43
-            uint32_t pixel[3];
44
-            HEADER_PIXEL(data, pixel);
45
-
46
-            uint32_t color = (pixel[0] >> 3) << 11;
47
-            color |= (pixel[1] >> 2) << 5;
48
-            color |= pixel[2] >> 3;
49
-            lcd_write_point(240 - x, y, color);
50
-        }
51
-    }
52
-}
33
+#include "text.h"
34
+#include "image.h"
53 35
 
54 36
 int main(void) {
55
-    heartbeat_init();
56
-    buttons_init();
37
+    // required for debug console
57 38
     cnsl_init();
58 39
     usb_init();
59 40
 
60 41
     debug("lcd_init");
61 42
     lcd_init();
62 43
     draw_splash();
63
-    lcd_set_backlight(0x8000);
44
+    lcd_set_backlight(0x1000);
64 45
 
65 46
     if (watchdog_caused_reboot()) {
66 47
         debug("reset by watchdog");
67 48
     }
68 49
 
50
+    debug("buttons_init");
51
+    buttons_init();
52
+
69 53
     // required for LiPo voltage reading
54
+    debug("adc_init");
70 55
     adc_init();
71 56
 
72 57
     // required for BLE and LiPo voltage reading
@@ -75,6 +60,9 @@ int main(void) {
75 60
         debug("cyw43_arch_init failed");
76 61
     }
77 62
 
63
+    debug("heartbeat_init");
64
+    heartbeat_init();
65
+
78 66
     debug("ble_init");
79 67
     ble_init();
80 68
 
@@ -85,6 +73,7 @@ int main(void) {
85 73
     watchdog_enable(1000, 1);
86 74
 
87 75
     debug("init done");
76
+    lcd_set_backlight(0x8000);
88 77
 
89 78
     while (1) {
90 79
         watchdog_update();

+ 112
- 0
src/text.c View File

@@ -0,0 +1,112 @@
1
+/*
2
+ * text.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include "config.h"
20
+#include "log.h"
21
+#include "lcd.h"
22
+#include "text.h"
23
+
24
+typedef struct {
25
+    struct text_conf *options;
26
+    uint16_t anchor;
27
+} state_t;
28
+
29
+static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
30
+                           void *state) {
31
+    state_t *s = (state_t*)state;
32
+
33
+    if (y < 0 || y >= s->options->height) return;
34
+    if (x < 0 || x + count >= s->options->width) return;
35
+
36
+    while (count--) {
37
+        uint32_t c = (alpha >> 3) << 11;
38
+        c |= (alpha >> 2) << 5;
39
+        c |= alpha >> 3;
40
+        lcd_write_point(240 - y - 1, x, c);
41
+        x++;
42
+    }
43
+}
44
+
45
+static uint8_t character_callback(int16_t x, int16_t y, mf_char character,
46
+                                  void *state) {
47
+    state_t *s = (state_t*)state;
48
+    uint8_t w = mf_render_character(s->options->font->font, x, y, character, pixel_callback, state);
49
+    return w;
50
+}
51
+
52
+static bool line_callback(const char *line, uint16_t count, void *state) {
53
+    state_t *s = (state_t*)state;
54
+
55
+    if (s->options->justify) {
56
+        mf_render_justified(s->options->font->font, s->anchor + s->options->x, s->options->y,
57
+                            s->options->width - s->options->margin * 2,
58
+                            line, count, character_callback, state);
59
+    } else {
60
+        mf_render_aligned(s->options->font->font, s->anchor + s->options->x, s->options->y,
61
+                          s->options->alignment, line, count,
62
+                          character_callback, state);
63
+    }
64
+
65
+    s->options->y += s->options->font->font->line_height;
66
+    return true;
67
+}
68
+
69
+void text_prepare_font(struct text_font *tf) {
70
+    if (!tf) {
71
+        debug("invalid param");
72
+        return;
73
+    }
74
+
75
+    const struct mf_font_s *font = mf_find_font(tf->fontname);
76
+    if (!font) {
77
+        debug("No such font: %s", tf->fontname);
78
+        return;
79
+    }
80
+
81
+    tf->font = font;
82
+
83
+    // TODO
84
+    //struct mf_scaledfont_s scaledfont;
85
+    //if (tf->scale > 1) {
86
+    //    mf_scale_font(&scaledfont, font, tf->scale, tf->scale);
87
+    //    tf->font = scaledfont.font;
88
+    //}
89
+}
90
+
91
+void text_draw(struct text_conf *tc) {
92
+    if ((!tc) || (!tc->font) || (!tc->font->font)) {
93
+        debug("invalid param");
94
+        return;
95
+    }
96
+
97
+    debug("'%s' %d", tc->text, tc->y);
98
+
99
+    state_t state;
100
+    state.options = tc;
101
+
102
+    if (tc->alignment == MF_ALIGN_LEFT) {
103
+        state.anchor = tc->margin;
104
+    } else if (tc->alignment == MF_ALIGN_CENTER) {
105
+        state.anchor = tc->width / 2;
106
+    } else if (tc->alignment == MF_ALIGN_RIGHT) {
107
+        state.anchor = tc->width - tc->margin;
108
+    }
109
+
110
+    mf_wordwrap(tc->font->font, tc->width - 2 * tc->margin,
111
+                tc->text, line_callback, &state);
112
+}

+ 3
- 0
src/util.c View File

@@ -37,6 +37,9 @@ void heartbeat_init(void) {
37 37
     gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
38 38
     gpio_put(PICO_DEFAULT_LED_PIN, 1);
39 39
 #endif // PICO_DEFAULT_LED_PIN
40
+#ifdef CYW43_WL_GPIO_LED_PIN
41
+    cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
42
+#endif // CYW43_WL_GPIO_LED_PIN
40 43
 }
41 44
 
42 45
 void heartbeat_run(void) {

Loading…
Cancel
Save