qmk_firmware

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

qp.c (10186B)


      1 // Copyright 2021 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include <quantum.h>
      5 #include <utf8.h>
      6 
      7 #include "qp_internal.h"
      8 #include "qp_comms.h"
      9 #include "qp_draw.h"
     10 
     11 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     12 // Internal driver validation
     13 
     14 static bool validate_driver_vtable(painter_driver_t *driver) {
     15     return (driver && driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false;
     16 }
     17 
     18 static bool validate_comms_vtable(painter_driver_t *driver) {
     19     return (driver && driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false;
     20 }
     21 
     22 static bool validate_driver_integrity(painter_driver_t *driver) {
     23     return validate_driver_vtable(driver) && validate_comms_vtable(driver);
     24 }
     25 
     26 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     27 // Quantum Painter External API: qp_init
     28 
     29 bool qp_init(painter_device_t device, painter_rotation_t rotation) {
     30     qp_dprintf("qp_init: entry\n");
     31     painter_driver_t *driver = (painter_driver_t *)device;
     32 
     33     if (!driver) {
     34         qp_dprintf("qp_init: fail (pointer to NULL)\n");
     35         return false;
     36     }
     37 
     38     driver->validate_ok = false;
     39     if (!validate_driver_integrity(driver)) {
     40         qp_dprintf("Failed to validate driver integrity in qp_init\n");
     41         return false;
     42     }
     43 
     44     driver->validate_ok = true;
     45 
     46     if (!qp_comms_init(device)) {
     47         driver->validate_ok = false;
     48         qp_dprintf("qp_init: fail (could not init comms)\n");
     49         return false;
     50     }
     51 
     52     if (!qp_comms_start(device)) {
     53         qp_dprintf("qp_init: fail (could not start comms)\n");
     54         return false;
     55     }
     56 
     57     // Set the rotation before init
     58     driver->rotation = rotation;
     59 
     60     // Invoke init
     61     bool ret = driver->driver_vtable->init(device, rotation);
     62     qp_comms_stop(device);
     63     qp_dprintf("qp_init: %s\n", ret ? "ok" : "fail");
     64     return ret;
     65 }
     66 
     67 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     68 // Quantum Painter External API: qp_power
     69 
     70 bool qp_power(painter_device_t device, bool power_on) {
     71     qp_dprintf("qp_power: entry\n");
     72     painter_driver_t *driver = (painter_driver_t *)device;
     73     if (!driver || !driver->validate_ok) {
     74         qp_dprintf("qp_power: fail (validation_ok == false)\n");
     75         return false;
     76     }
     77 
     78     if (!qp_comms_start(device)) {
     79         qp_dprintf("qp_power: fail (could not start comms)\n");
     80         return false;
     81     }
     82 
     83     bool ret = driver->driver_vtable->power(device, power_on);
     84     qp_comms_stop(device);
     85     qp_dprintf("qp_power: %s\n", ret ? "ok" : "fail");
     86     return ret;
     87 }
     88 
     89 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     90 // Quantum Painter External API: qp_clear
     91 
     92 bool qp_clear(painter_device_t device) {
     93     qp_dprintf("qp_clear: entry\n");
     94     painter_driver_t *driver = (painter_driver_t *)device;
     95     if (!driver || !driver->validate_ok) {
     96         qp_dprintf("qp_clear: fail (validation_ok == false)\n");
     97         return false;
     98     }
     99 
    100     if (!qp_comms_start(device)) {
    101         qp_dprintf("qp_clear: fail (could not start comms)\n");
    102         return false;
    103     }
    104 
    105     bool ret = driver->driver_vtable->clear(device);
    106     qp_comms_stop(device);
    107     qp_dprintf("qp_clear: %s\n", ret ? "ok" : "fail");
    108     return ret;
    109 }
    110 
    111 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    112 // Quantum Painter External API: qp_flush
    113 
    114 bool qp_flush(painter_device_t device) {
    115     qp_dprintf("qp_flush: entry\n");
    116     painter_driver_t *driver = (painter_driver_t *)device;
    117     if (!driver || !driver->validate_ok) {
    118         qp_dprintf("qp_flush: fail (validation_ok == false)\n");
    119         return false;
    120     }
    121 
    122     if (!qp_comms_start(device)) {
    123         qp_dprintf("qp_flush: fail (could not start comms)\n");
    124         return false;
    125     }
    126 
    127     bool ret = driver->driver_vtable->flush(device);
    128     qp_comms_stop(device);
    129     qp_dprintf("qp_flush: %s\n", ret ? "ok" : "fail");
    130     return ret;
    131 }
    132 
    133 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    134 // Quantum Painter External API: qp_get_*
    135 
    136 uint16_t qp_get_width(painter_device_t device) {
    137     qp_dprintf("qp_get_width: entry\n");
    138     painter_driver_t *driver = (painter_driver_t *)device;
    139 
    140     if (!driver || !driver->validate_ok) {
    141         qp_dprintf("qp_get_width: fail (invalid driver)\n");
    142         return 0;
    143     }
    144 
    145     uint16_t width;
    146     switch (driver->rotation) {
    147         default:
    148         case QP_ROTATION_0:
    149         case QP_ROTATION_180:
    150             width = driver->panel_width;
    151             break;
    152         case QP_ROTATION_90:
    153         case QP_ROTATION_270:
    154             width = driver->panel_height;
    155             break;
    156     }
    157 
    158     qp_dprintf("qp_get_width: ok\n");
    159     return width;
    160 }
    161 
    162 uint16_t qp_get_height(painter_device_t device) {
    163     qp_dprintf("qp_get_height: entry\n");
    164     painter_driver_t *driver = (painter_driver_t *)device;
    165 
    166     if (!driver || !driver->validate_ok) {
    167         qp_dprintf("qp_get_height: fail (invalid driver)\n");
    168         return 0;
    169     }
    170 
    171     uint16_t height;
    172     switch (driver->rotation) {
    173         default:
    174         case QP_ROTATION_0:
    175         case QP_ROTATION_180:
    176             height = driver->panel_height;
    177             break;
    178         case QP_ROTATION_90:
    179         case QP_ROTATION_270:
    180             height = driver->panel_width;
    181             break;
    182     }
    183 
    184     qp_dprintf("qp_get_height: ok\n");
    185     return height;
    186 }
    187 
    188 painter_rotation_t qp_get_rotation(painter_device_t device) {
    189     qp_dprintf("qp_get_rotation: entry\n");
    190     painter_driver_t *driver = (painter_driver_t *)device;
    191 
    192     if (!driver || !driver->validate_ok) {
    193         qp_dprintf("qp_get_rotation: fail (invalid driver)\n");
    194         return QP_ROTATION_0;
    195     }
    196 
    197     qp_dprintf("qp_get_rotation: ok\n");
    198     return driver->rotation;
    199 }
    200 
    201 uint16_t qp_get_offset_x(painter_device_t device) {
    202     qp_dprintf("qp_get_offset_x: entry\n");
    203     painter_driver_t *driver = (painter_driver_t *)device;
    204 
    205     if (!driver || !driver->validate_ok) {
    206         qp_dprintf("qp_get_offset_x: fail (invalid driver)\n");
    207         return 0;
    208     }
    209 
    210     qp_dprintf("qp_get_offset_x: ok\n");
    211     return driver->offset_x;
    212 }
    213 
    214 uint16_t qp_get_offset_y(painter_device_t device) {
    215     qp_dprintf("qp_get_offset_y: entry\n");
    216     painter_driver_t *driver = (painter_driver_t *)device;
    217 
    218     if (!driver || !driver->validate_ok) {
    219         qp_dprintf("qp_get_offset_y: fail (invalid driver)\n");
    220         return 0;
    221     }
    222 
    223     qp_dprintf("qp_get_offset_y: ok\n");
    224     return driver->offset_y;
    225 }
    226 
    227 void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) {
    228     qp_dprintf("qp_geometry: entry\n");
    229     painter_driver_t *driver = (painter_driver_t *)device;
    230 
    231     if (!driver || !driver->validate_ok) {
    232         qp_dprintf("qp_geometry: fail (invalid driver)\n");
    233         return;
    234     }
    235 
    236     if (width) {
    237         *width = qp_get_width(device);
    238     }
    239 
    240     if (height) {
    241         *height = qp_get_height(device);
    242     }
    243 
    244     if (rotation) {
    245         *rotation = qp_get_rotation(device);
    246     }
    247 
    248     if (offset_x) {
    249         *offset_x = qp_get_offset_x(device);
    250     }
    251 
    252     if (offset_y) {
    253         *offset_y = qp_get_offset_y(device);
    254     }
    255 
    256     qp_dprintf("qp_get_geometry: ok\n");
    257 }
    258 
    259 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    260 // Quantum Painter External API: qp_set_viewport_offsets
    261 
    262 void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_t offset_y) {
    263     qp_dprintf("qp_set_viewport_offsets: entry\n");
    264     painter_driver_t *driver = (painter_driver_t *)device;
    265 
    266     if (!driver) {
    267         qp_dprintf("qp_set_viewport_offsets: fail (pointer to NULL)\n");
    268         return;
    269     }
    270 
    271     driver->offset_x = offset_x;
    272     driver->offset_y = offset_y;
    273 
    274     qp_dprintf("qp_set_viewport_offsets: ok\n");
    275 }
    276 
    277 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    278 // Quantum Painter External API: qp_viewport
    279 
    280 bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
    281     qp_dprintf("qp_viewport: entry\n");
    282     painter_driver_t *driver = (painter_driver_t *)device;
    283     if (!driver || !driver->validate_ok) {
    284         qp_dprintf("qp_viewport: fail (validation_ok == false)\n");
    285         return false;
    286     }
    287 
    288     if (!qp_comms_start(device)) {
    289         qp_dprintf("qp_viewport: fail (could not start comms)\n");
    290         return false;
    291     }
    292 
    293     // Set the viewport
    294     bool ret = driver->driver_vtable->viewport(device, left, top, right, bottom);
    295     qp_dprintf("qp_viewport: %s\n", ret ? "ok" : "fail");
    296     qp_comms_stop(device);
    297     return ret;
    298 }
    299 
    300 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    301 // Quantum Painter External API: qp_pixdata
    302 
    303 bool qp_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {
    304     qp_dprintf("qp_pixdata: entry\n");
    305     painter_driver_t *driver = (painter_driver_t *)device;
    306     if (!driver || !driver->validate_ok) {
    307         qp_dprintf("qp_pixdata: fail (validation_ok == false)\n");
    308         return false;
    309     }
    310 
    311     if (!qp_comms_start(device)) {
    312         qp_dprintf("qp_pixdata: fail (could not start comms)\n");
    313         return false;
    314     }
    315 
    316     bool ret = driver->driver_vtable->pixdata(device, pixel_data, native_pixel_count);
    317     qp_dprintf("qp_pixdata: %s\n", ret ? "ok" : "fail");
    318     qp_comms_stop(device);
    319     return ret;
    320 }