display.c (6379B)
1 // Copyright 2023 Dasky (@daskygit) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #include "display.h" 5 #include "graphics/splash.qgf.h" 6 #include "graphics/reverb.qgf.h" 7 #include "graphics/robotomono20.qff.h" 8 #include <stdio.h> 9 #include <math.h> 10 11 static painter_image_handle_t reverb_logo; 12 static painter_image_handle_t splash_image; 13 static deferred_token display_task_token; 14 static uint32_t key_pressed_count = 0; 15 16 static uint8_t reverb_surface_fb[SURFACE_REQUIRED_BUFFER_BYTE_SIZE(240, 240, 16)]; 17 18 painter_device_t reverb_surface; 19 painter_device_t reverb_display; 20 painter_font_handle_t roboto_font; 21 22 uint32_t display_task_callback(uint32_t trigger_time, void *cb_arg) { 23 display_task_kb(); 24 return 100; 25 } 26 27 void display_init_kb(void) { 28 reverb_display = qp_gc9a01_make_spi_device(240, 240, DISPLAY_CS, DISPLAY_DC, DISPLAY_RST, 2, 0); // always init display 29 qp_init(reverb_display, QP_ROTATION_0); 30 roboto_font = qp_load_font_mem(font_robotomono20); 31 reverb_surface = qp_make_rgb565_surface(240, 240, reverb_surface_fb); 32 qp_init(reverb_surface, QP_ROTATION_0); 33 if (!display_init_user()) { 34 return; 35 } 36 splash_image = qp_load_image_mem(gfx_splash); 37 reverb_logo = qp_load_image_mem(gfx_reverb); 38 qp_drawimage(reverb_display, 0, 0, splash_image); 39 qp_flush(reverb_display); 40 qp_close_image(splash_image); 41 display_task_token = defer_exec(2000, display_task_callback, NULL); 42 } 43 44 __attribute__((weak)) bool display_init_user(void) { 45 return true; 46 } 47 48 void display_task_kb(void) { 49 if (!display_task_user()) { 50 return; 51 } 52 static bool first_draw = true; 53 static uint32_t last_timer = 0; 54 static uint32_t last_wpm = UINT32_MAX; 55 static uint32_t last_scan_rate = 0; 56 static uint32_t last_key_pressed_count = UINT32_MAX; 57 static uint8_t last_hue = 0; 58 static uint8_t last_sat = 0; 59 static uint8_t last_val = 0; 60 bool rgb_redraw = false; 61 62 if (first_draw) { 63 qp_rect(reverb_display, 0, 0, 239, 239, 0, 0, 0, true); 64 first_draw = false; 65 } 66 67 char buffer[64] = {0}; 68 69 if (last_hue != rgb_matrix_get_hue() || last_sat != rgb_matrix_get_sat() || last_val != rgb_matrix_get_val()) { 70 last_hue = rgb_matrix_get_hue(); 71 last_sat = rgb_matrix_get_sat(); 72 last_val = rgb_matrix_get_val(); 73 qp_drawimage_recolor(reverb_surface, 60, 40, reverb_logo, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), 0, 0, 0); 74 rgb_redraw = true; 75 } 76 77 if (rgb_redraw || last_scan_rate != get_matrix_scan_rate()) { 78 snprintf(buffer, sizeof(buffer), "Scan Rate %ld", get_matrix_scan_rate()); 79 int16_t width = qp_textwidth(roboto_font, buffer); 80 qp_line(reverb_surface, 17, 101, 220, 101, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128)); 81 qp_rect(reverb_surface, 16, 125 - roboto_font->line_height, 221, 125, 0, 0, 0, true); 82 qp_drawtext_recolor(reverb_surface, (120 - (width / 2)), (125 - roboto_font->line_height), roboto_font, buffer, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), 0, 0, 0); 83 qp_line(reverb_surface, 16, 126, 221, 126, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128)); 84 last_scan_rate = get_matrix_scan_rate(); 85 } 86 if (rgb_redraw || last_key_pressed_count != key_pressed_count) { 87 snprintf(buffer, sizeof(buffer), "Keys Pressed"); 88 int16_t width = qp_textwidth(roboto_font, buffer); 89 qp_rect(reverb_surface, 30, 150 - roboto_font->line_height, 209, 150, 0, 0, 0, true); 90 qp_drawtext_recolor(reverb_surface, (120 - (width / 2)), (150 - roboto_font->line_height), roboto_font, buffer, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), 0, 0, 0); 91 snprintf(buffer, sizeof(buffer), "%ld", key_pressed_count); 92 width = qp_textwidth(roboto_font, buffer); 93 qp_rect(reverb_surface, 30, 172 - roboto_font->line_height, 173, 172, 0, 0, 0, true); 94 qp_drawtext_recolor(reverb_surface, (120 - (width / 2)), (172 - roboto_font->line_height), roboto_font, buffer, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), 0, 0, 0); 95 qp_line(reverb_surface, 30, 173, 209, 173, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128)); 96 last_key_pressed_count = key_pressed_count; 97 } 98 if (rgb_redraw || last_wpm != get_current_wpm()) { 99 snprintf(buffer, sizeof(buffer), "WPM %d", get_current_wpm()); 100 int16_t width = qp_textwidth(roboto_font, buffer); 101 qp_rect(reverb_surface, 56, 200 - roboto_font->line_height, 184, 200, 0, 0, 0, true); 102 qp_drawtext_recolor(reverb_surface, (120 - (width / 2)), (200 - roboto_font->line_height), roboto_font, buffer, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), 0, 0, 0); 103 qp_line(reverb_surface, 56, 201, 184, 201, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128)); 104 last_wpm = get_current_wpm(); 105 } 106 107 if (rgb_redraw || timer_elapsed(last_timer) >= 1000) { 108 static uint8_t seconds = 0; 109 static uint8_t x = 0; 110 static uint8_t y = 0; 111 if (x && y) { 112 qp_circle(reverb_surface, x, y, 4, 0, 0, 0, true); 113 } 114 double radians = 0.10471975511966 * seconds; 115 x = (110 * cos(radians)) + 119; 116 y = (110 * sin(radians)) + 119; 117 qp_circle(reverb_surface, x, y, 4, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), true); 118 qp_circle(reverb_surface, 119, 119, 105, rgb_matrix_get_hue(), rgb_matrix_get_sat(), MAX(rgb_matrix_get_val(), 128), false); 119 if (seconds == 59) { 120 seconds = 0; 121 } else if (timer_elapsed(last_timer) >= 1000) { 122 last_timer = timer_read32(); 123 seconds++; 124 } 125 } 126 127 qp_surface_draw(reverb_surface, reverb_display, 0, 0, rgb_redraw); 128 } 129 130 __attribute__((weak)) bool display_task_user(void) { 131 return true; 132 } 133 134 void display_key_counter(void) { 135 if (key_pressed_count == UINT32_MAX) { 136 key_pressed_count = 0; 137 } 138 key_pressed_count++; 139 }