qmk_firmware

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

qp_comms_spi.c (5655B)


      1 // Copyright 2021 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #ifdef QUANTUM_PAINTER_SPI_ENABLE
      5 
      6 #    include "spi_master.h"
      7 #    include "qp_comms_spi.h"
      8 
      9 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     10 // Base SPI support
     11 
     12 bool qp_comms_spi_init(painter_device_t device) {
     13     painter_driver_t      *driver       = (painter_driver_t *)device;
     14     qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config;
     15 
     16     // Initialize the SPI peripheral
     17     spi_init();
     18 
     19     // Set up CS as output high
     20     gpio_set_pin_output(comms_config->chip_select_pin);
     21     gpio_write_pin_high(comms_config->chip_select_pin);
     22 
     23     return true;
     24 }
     25 
     26 bool qp_comms_spi_start(painter_device_t device) {
     27     painter_driver_t      *driver       = (painter_driver_t *)device;
     28     qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config;
     29 
     30     return spi_start(comms_config->chip_select_pin, comms_config->lsb_first, comms_config->mode, comms_config->divisor);
     31 }
     32 
     33 uint32_t qp_comms_spi_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
     34     uint32_t       bytes_remaining = byte_count;
     35     const uint8_t *p               = (const uint8_t *)data;
     36     const uint32_t max_msg_length  = 1024;
     37 
     38     while (bytes_remaining > 0) {
     39         uint32_t bytes_this_loop = MIN(bytes_remaining, max_msg_length);
     40         spi_transmit(p, bytes_this_loop);
     41         p += bytes_this_loop;
     42         bytes_remaining -= bytes_this_loop;
     43     }
     44 
     45     return byte_count - bytes_remaining;
     46 }
     47 
     48 bool qp_comms_spi_stop(painter_device_t device) {
     49     painter_driver_t      *driver       = (painter_driver_t *)device;
     50     qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config;
     51     spi_stop();
     52     gpio_write_pin_high(comms_config->chip_select_pin);
     53     return true;
     54 }
     55 
     56 const painter_comms_vtable_t spi_comms_vtable = {
     57     .comms_init  = qp_comms_spi_init,
     58     .comms_start = qp_comms_spi_start,
     59     .comms_send  = qp_comms_spi_send_data,
     60     .comms_stop  = qp_comms_spi_stop,
     61 };
     62 
     63 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     64 // SPI with D/C and RST pins
     65 
     66 #    ifdef QUANTUM_PAINTER_SPI_DC_RESET_ENABLE
     67 
     68 bool qp_comms_spi_dc_reset_init(painter_device_t device) {
     69     if (!qp_comms_spi_init(device)) {
     70         return false;
     71     }
     72 
     73     painter_driver_t               *driver       = (painter_driver_t *)device;
     74     qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
     75 
     76     // Set up D/C as output low, if specified
     77     if (comms_config->dc_pin != NO_PIN) {
     78         gpio_set_pin_output(comms_config->dc_pin);
     79         gpio_write_pin_low(comms_config->dc_pin);
     80     }
     81 
     82     // Set up RST as output, if specified, performing a reset in the process
     83     if (comms_config->reset_pin != NO_PIN) {
     84         gpio_set_pin_output(comms_config->reset_pin);
     85         gpio_write_pin_low(comms_config->reset_pin);
     86         wait_ms(20);
     87         gpio_write_pin_high(comms_config->reset_pin);
     88         wait_ms(20);
     89     }
     90 
     91     return true;
     92 }
     93 
     94 uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
     95     painter_driver_t               *driver       = (painter_driver_t *)device;
     96     qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
     97     gpio_write_pin_high(comms_config->dc_pin);
     98     return qp_comms_spi_send_data(device, data, byte_count);
     99 }
    100 
    101 bool qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) {
    102     painter_driver_t               *driver       = (painter_driver_t *)device;
    103     qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
    104     gpio_write_pin_low(comms_config->dc_pin);
    105     spi_write(cmd);
    106     return true;
    107 }
    108 
    109 bool qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
    110     painter_driver_t               *driver       = (painter_driver_t *)device;
    111     qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
    112     for (size_t i = 0; i < sequence_len;) {
    113         uint8_t command   = sequence[i];
    114         uint8_t delay     = sequence[i + 1];
    115         uint8_t num_bytes = sequence[i + 2];
    116         qp_comms_spi_dc_reset_send_command(device, command);
    117         if (num_bytes > 0) {
    118             if (comms_config->command_params_uses_command_pin) {
    119                 for (uint8_t j = 0; j < num_bytes; j++) {
    120                     qp_comms_spi_dc_reset_send_command(device, sequence[i + 3 + j]);
    121                 }
    122             } else {
    123                 qp_comms_spi_dc_reset_send_data(device, &sequence[i + 3], num_bytes);
    124             }
    125         }
    126         if (delay > 0) {
    127             wait_ms(delay);
    128         }
    129         i += (3 + num_bytes);
    130     }
    131 
    132     return true;
    133 }
    134 
    135 const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = {
    136     .base =
    137         {
    138             .comms_init  = qp_comms_spi_dc_reset_init,
    139             .comms_start = qp_comms_spi_start,
    140             .comms_send  = qp_comms_spi_dc_reset_send_data,
    141             .comms_stop  = qp_comms_spi_stop,
    142         },
    143     .send_command          = qp_comms_spi_dc_reset_send_command,
    144     .bulk_command_sequence = qp_comms_spi_dc_reset_bulk_command_sequence,
    145 };
    146 
    147 #    endif // QUANTUM_PAINTER_SPI_DC_RESET_ENABLE
    148 
    149 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    150 
    151 #endif // QUANTUM_PAINTER_SPI_ENABLE