Browse Source

support arbitrary blended text colors

Thomas Buck 7 months ago
parent
commit
822302d3e8
7 changed files with 86 additions and 4 deletions
  1. 5
    0
      include/lcd.h
  2. 1
    0
      include/text.h
  3. 2
    0
      include/util.h
  4. 15
    2
      src/image.c
  5. 34
    0
      src/lcd.c
  6. 22
    2
      src/text.c
  7. 7
    0
      src/util.c

+ 5
- 0
include/lcd.h View File

@@ -26,6 +26,11 @@
26 26
     | (((g) >> 2) << 5)    \
27 27
     |  ((b) >> 3)          \
28 28
 )
29
+#define RGB_565_REV(c)            \
30
+    ((c & 0xF800) >> 8) / 255.0f, \
31
+    ((c & 0x07E0) >> 3) / 255.0f, \
32
+    ((c & 0x001F) << 3) / 255.0f
33
+uint32_t from_hsv(float h, float s, float v);
29 34
 
30 35
 void lcd_init(void);
31 36
 

+ 1
- 0
include/text.h View File

@@ -39,6 +39,7 @@ struct text_conf {
39 39
     int width;
40 40
     int height;
41 41
     int margin;
42
+    int fg;
42 43
     int bg;
43 44
 
44 45
     struct text_font *font;

+ 2
- 0
include/util.h View File

@@ -31,4 +31,6 @@ void reset_to_main(void);
31 31
 
32 32
 void hexdump(uint8_t *buff, size_t len);
33 33
 
34
+float map(float value, float leftMin, float leftMax, float rightMin, float rightMax);
35
+
34 36
 #endif // __UTIL_H__

+ 15
- 2
src/image.c View File

@@ -22,6 +22,7 @@
22 22
 #include "lcd.h"
23 23
 #include "text.h"
24 24
 #include "lipo.h"
25
+#include "util.h"
25 26
 #include "image.h"
26 27
 
27 28
 #pragma GCC diagnostic push
@@ -65,6 +66,7 @@ void draw_splash(void) {
65 66
         .width = 240,
66 67
         .height = 240,
67 68
         .margin = 2,
69
+        .fg = RGB_565(0xFF, 0xFF, 0xFF),
68 70
         .bg = RGB_565(0x00, 0x00, 0x00),
69 71
         .font = &font_big,
70 72
     };
@@ -79,6 +81,7 @@ void draw_splash(void) {
79 81
         .width = 240,
80 82
         .height = 240,
81 83
         .margin = 2,
84
+        .fg = RGB_565(0xFF, 0xFF, 0xFF),
82 85
         .bg = RGB_565(0x00, 0x00, 0x00),
83 86
         .font = &font_small,
84 87
     };
@@ -86,13 +89,22 @@ void draw_splash(void) {
86 89
 }
87 90
 
88 91
 void draw_battery_indicator(void) {
89
-    float v = lipo_voltage();
92
+    static const float batt_warn_limit = 15.0f;
90 93
     static char s[30];
94
+    float v = lipo_voltage();
95
+    uint32_t c = RGB_565(0xFF, 0x00, 0x00);
91 96
     if (lipo_charging()) {
92 97
         //                     "Batt:   99.9%   (4.20V)"
93 98
         snprintf(s, sizeof(s), "Batt: Charging! (%.2fV)", v);
99
+        c = RGB_565(0xFF, 0xFF, 0x00);
94 100
     } else {
95
-        snprintf(s, sizeof(s), "Batt:   %02.1f%%   (%.2fV)", lipo_percentage(v), v);
101
+        float percentage = lipo_percentage(v);
102
+        snprintf(s, sizeof(s), "Batt:   %02.1f%%   (%.2fV)", percentage, v);
103
+
104
+        if (percentage > batt_warn_limit) {
105
+            float hue = map(percentage, batt_warn_limit, 100, 0.0, 0.333);
106
+            c = from_hsv(hue, 1.0, 1.0);
107
+        }
96 108
     }
97 109
 
98 110
     static struct text_font font = {
@@ -112,6 +124,7 @@ void draw_battery_indicator(void) {
112 124
         .width = 240,
113 125
         .height = 240,
114 126
         .margin = 2,
127
+        .fg = c,
115 128
         .bg = RGB_565(0x00, 0x00, 0x00),
116 129
         .font = &font,
117 130
     };

+ 34
- 0
src/lcd.c View File

@@ -16,6 +16,8 @@
16 16
  * See <http://www.gnu.org/licenses/>.
17 17
  */
18 18
 
19
+#include <math.h>
20
+
19 21
 #include "pico/stdlib.h"
20 22
 #include "hardware/spi.h"
21 23
 #include "hardware/pwm.h"
@@ -273,3 +275,35 @@ void lcd_write_point(uint16_t x, uint16_t y, uint32_t color) {
273 275
 void lcd_write_rect(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint32_t color) {
274 276
     st7789_fill_rect(&gs_handle, left, top, right, bottom, color);
275 277
 }
278
+
279
+uint32_t from_hsv(float h, float s, float v) {
280
+    float i = floorf(h * 6.0f);
281
+    float f = h * 6.0f - i;
282
+    v *= 255.0f;
283
+    float p = v * (1.0f - s);
284
+    float q = v * (1.0f - f * s);
285
+    float t = v * (1.0f - (1.0f - f) * s);
286
+
287
+    switch (((uint32_t)i) % 6) {
288
+    case 0:
289
+        return RGB_565((uint32_t)v, (uint32_t)t, (uint32_t)p);
290
+
291
+    case 1:
292
+        return RGB_565((uint32_t)q, (uint32_t)v, (uint32_t)p);
293
+
294
+    case 2:
295
+        return RGB_565((uint32_t)p, (uint32_t)v, (uint32_t)t);
296
+
297
+    case 3:
298
+        return RGB_565((uint32_t)p, (uint32_t)q, (uint32_t)v);
299
+
300
+    case 4:
301
+        return RGB_565((uint32_t)t, (uint32_t)p, (uint32_t)v);
302
+
303
+    case 5:
304
+        return RGB_565((uint32_t)v, (uint32_t)p, (uint32_t)q);
305
+
306
+    default:
307
+        return RGB_565(0, 0, 0);
308
+    }
309
+}

+ 22
- 2
src/text.c View File

@@ -26,6 +26,26 @@ typedef struct {
26 26
     uint16_t anchor;
27 27
 } state_t;
28 28
 
29
+static uint32_t blend(uint32_t fg_c, uint32_t bg_c, uint8_t alpha) {
30
+    float bg[4] = { RGB_565_REV(bg_c), 1.0f };
31
+    float fg[4] = { RGB_565_REV(fg_c), alpha / 255.0f };
32
+    float r[4];
33
+    r[3] = 1.0f - (1.0f - fg[3]) * (1.0f - bg[3]);
34
+    if (r[3] < 1.0e-6f) {
35
+        r[0] = 0.0f;
36
+        r[1] = 0.0f;
37
+        r[2] = 0.0f;
38
+    } else {
39
+        r[0] = fg[0] * fg[3] / r[3] + bg[0] * bg[3] * (1.0f - fg[3]) / r[3];
40
+        r[1] = fg[1] * fg[3] / r[3] + bg[1] * bg[3] * (1.0f - fg[3]) / r[3];
41
+        r[2] = fg[2] * fg[3] / r[3] + bg[2] * bg[3] * (1.0f - fg[3]) / r[3];
42
+    }
43
+
44
+    return RGB_565((uint32_t)(r[0] * 255.0f),
45
+                   (uint32_t)(r[1] * 255.0f),
46
+                   (uint32_t)(r[2] * 255.0f));
47
+}
48
+
29 49
 static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
30 50
                            void *state) {
31 51
     state_t *s = (state_t*)state;
@@ -34,8 +54,8 @@ static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
34 54
     if (x < 0 || x + count >= s->options->width) return;
35 55
 
36 56
     while (count--) {
37
-        uint32_t c = RGB_565(alpha, alpha, alpha);
38
-        lcd_write_point(240 - y - 1, x, c);
57
+        lcd_write_point(240 - y - 1, x,
58
+                        blend(s->options->fg, s->options->bg, alpha));
39 59
         x++;
40 60
     }
41 61
 }

+ 7
- 0
src/util.c View File

@@ -100,3 +100,10 @@ void hexdump(uint8_t *buff, size_t len) {
100 100
         println();
101 101
     }
102 102
 }
103
+
104
+float map(float value, float leftMin, float leftMax, float rightMin, float rightMax) {
105
+    float leftSpan = leftMax - leftMin;
106
+    float rightSpan = rightMax - rightMin;
107
+    float valueScaled = (value - leftMin) / leftSpan;
108
+    return rightMin + (valueScaled * rightSpan);
109
+}

Loading…
Cancel
Save