qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

qp_tft_panel.c (5549B)


      1 // Copyright 2021 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include "color.h"
      5 #include "qp_internal.h"
      6 #include "qp_comms.h"
      7 #include "qp_draw.h"
      8 #include "qp_tft_panel.h"
      9 
     10 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     11 // Quantum Painter API implementations
     12 
     13 // Power control
     14 bool qp_tft_panel_power(painter_device_t device, bool power_on) {
     15     painter_driver_t                           *driver = (painter_driver_t *)device;
     16     tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable;
     17     qp_comms_command(device, power_on ? vtable->opcodes.display_on : vtable->opcodes.display_off);
     18     return true;
     19 }
     20 
     21 // Screen clear
     22 bool qp_tft_panel_clear(painter_device_t device) {
     23     painter_driver_t *driver = (painter_driver_t *)device;
     24     driver->driver_vtable->init(device, driver->rotation); // Re-init the LCD
     25     return true;
     26 }
     27 
     28 // Screen flush
     29 bool qp_tft_panel_flush(painter_device_t device) {
     30     // No-op, as there's no framebuffer in RAM for this device.
     31     return true;
     32 }
     33 
     34 // Viewport to draw to
     35 bool qp_tft_panel_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
     36     painter_driver_t                           *driver = (painter_driver_t *)device;
     37     tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable;
     38 
     39     // Fix up the drawing location if required
     40     left += driver->offset_x;
     41     right += driver->offset_x;
     42     top += driver->offset_y;
     43     bottom += driver->offset_y;
     44 
     45     // Check if we need to manually swap the window coordinates based on whether or not we're in a sideways rotation
     46     if (vtable->swap_window_coords && (driver->rotation == QP_ROTATION_90 || driver->rotation == QP_ROTATION_270)) {
     47         uint16_t temp;
     48 
     49         temp = left;
     50         left = top;
     51         top  = temp;
     52 
     53         temp   = right;
     54         right  = bottom;
     55         bottom = temp;
     56     }
     57 
     58     if (vtable->num_window_bytes == 1) {
     59         // Set up the x-window
     60         uint8_t xbuf[2] = {left & 0xFF, right & 0xFF};
     61         qp_comms_command_databuf(device, vtable->opcodes.set_column_address, xbuf, sizeof(xbuf));
     62 
     63         // Set up the y-window
     64         uint8_t ybuf[2] = {top & 0xFF, bottom & 0xFF};
     65         qp_comms_command_databuf(device, vtable->opcodes.set_row_address, ybuf, sizeof(ybuf));
     66     } else if (vtable->num_window_bytes == 2) {
     67         // Set up the x-window
     68         uint8_t xbuf[4] = {left >> 8, left & 0xFF, right >> 8, right & 0xFF};
     69         qp_comms_command_databuf(device, vtable->opcodes.set_column_address, xbuf, sizeof(xbuf));
     70 
     71         // Set up the y-window
     72         uint8_t ybuf[4] = {top >> 8, top & 0xFF, bottom >> 8, bottom & 0xFF};
     73         qp_comms_command_databuf(device, vtable->opcodes.set_row_address, ybuf, sizeof(ybuf));
     74     }
     75 
     76     // Lock in the window
     77     qp_comms_command(device, vtable->opcodes.enable_writes);
     78     return true;
     79 }
     80 
     81 // Stream pixel data to the current write position in GRAM
     82 bool qp_tft_panel_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {
     83     painter_driver_t *driver = (painter_driver_t *)device;
     84     qp_comms_send(device, pixel_data, native_pixel_count * driver->native_bits_per_pixel / 8);
     85     return true;
     86 }
     87 
     88 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     89 // Convert supplied palette entries into their native equivalents
     90 
     91 bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
     92     for (int16_t i = 0; i < palette_size; ++i) {
     93         rgb_t    rgb      = hsv_to_rgb_nocie(palette[i].hsv888);
     94         uint16_t rgb565   = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3);
     95         palette[i].rgb565 = __builtin_bswap16(rgb565);
     96     }
     97     return true;
     98 }
     99 
    100 bool qp_tft_panel_palette_convert_rgb888(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
    101     for (int16_t i = 0; i < palette_size; ++i) {
    102         palette[i].rgb888 = hsv_to_rgb_nocie(palette[i].hsv888);
    103     }
    104     return true;
    105 }
    106 
    107 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    108 // Append pixels to the target location, keyed by the pixel index
    109 
    110 bool qp_tft_panel_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
    111     uint16_t *buf = (uint16_t *)target_buffer;
    112     for (uint32_t i = 0; i < pixel_count; ++i) {
    113         buf[pixel_offset + i] = palette[palette_indices[i]].rgb565;
    114     }
    115     return true;
    116 }
    117 
    118 bool qp_tft_panel_append_pixels_rgb888(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
    119     for (uint32_t i = 0; i < pixel_count; ++i) {
    120         target_buffer[(pixel_offset + i) * 3 + 0] = palette[palette_indices[i]].rgb888.r;
    121         target_buffer[(pixel_offset + i) * 3 + 1] = palette[palette_indices[i]].rgb888.g;
    122         target_buffer[(pixel_offset + i) * 3 + 2] = palette[palette_indices[i]].rgb888.b;
    123     }
    124     return true;
    125 }
    126 
    127 bool qp_tft_panel_append_pixdata(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) {
    128     target_buffer[pixdata_offset] = pixdata_byte;
    129     return true;
    130 }