qmk_firmware

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

qp_comms_i2c.c (3154B)


      1 // Copyright 2022 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #ifdef QUANTUM_PAINTER_I2C_ENABLE
      5 
      6 #    include "i2c_master.h"
      7 #    include "qp_comms_i2c.h"
      8 
      9 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     10 // Helpers
     11 
     12 static uint32_t qp_comms_i2c_send_raw(painter_device_t device, const void *data, uint32_t byte_count) {
     13     painter_driver_t      *driver       = (painter_driver_t *)device;
     14     qp_comms_i2c_config_t *comms_config = (qp_comms_i2c_config_t *)driver->comms_config;
     15     i2c_status_t           res          = i2c_transmit(comms_config->chip_address << 1, data, byte_count, I2C_TIMEOUT);
     16     if (res < 0) {
     17         return 0;
     18     }
     19     return byte_count;
     20 }
     21 
     22 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     23 // Base I2C support
     24 
     25 bool qp_comms_i2c_init(painter_device_t device) {
     26     i2c_init();
     27     return true;
     28 }
     29 
     30 bool qp_comms_i2c_start(painter_device_t device) {
     31     return true;
     32 }
     33 
     34 uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
     35     return qp_comms_i2c_send_raw(device, data, byte_count);
     36 }
     37 
     38 bool qp_comms_i2c_stop(painter_device_t device) {
     39     return true;
     40 }
     41 
     42 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     43 // Command+Data I2C support
     44 
     45 static const uint8_t cmd_byte  = 0x00;
     46 static const uint8_t data_byte = 0x40;
     47 
     48 bool qp_comms_i2c_cmddata_send_command(painter_device_t device, uint8_t cmd) {
     49     uint8_t buf[2] = {cmd_byte, cmd};
     50     return qp_comms_i2c_send_raw(device, &buf, 2);
     51 }
     52 
     53 uint32_t qp_comms_i2c_cmddata_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
     54     uint8_t buf[1 + byte_count];
     55     buf[0] = data_byte;
     56     memcpy(&buf[1], data, byte_count);
     57     if (qp_comms_i2c_send_raw(device, buf, sizeof(buf)) != sizeof(buf)) {
     58         return 0;
     59     }
     60     return byte_count;
     61 }
     62 
     63 bool qp_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
     64     uint8_t buf[32];
     65     for (size_t i = 0; i < sequence_len;) {
     66         uint8_t command   = sequence[i];
     67         uint8_t delay     = sequence[i + 1];
     68         uint8_t num_bytes = sequence[i + 2];
     69         buf[0]            = cmd_byte;
     70         buf[1]            = command;
     71         memcpy(&buf[2], &sequence[i + 3], num_bytes);
     72         if (!qp_comms_i2c_send_raw(device, buf, num_bytes + 2)) {
     73             return false;
     74         }
     75 
     76         if (delay > 0) {
     77             wait_ms(delay);
     78         }
     79         i += (3 + num_bytes);
     80     }
     81 
     82     return true;
     83 }
     84 
     85 const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable = {
     86     .base =
     87         {
     88             .comms_init  = qp_comms_i2c_init,
     89             .comms_start = qp_comms_i2c_start,
     90             .comms_send  = qp_comms_i2c_cmddata_send_data,
     91             .comms_stop  = qp_comms_i2c_stop,
     92         },
     93     .send_command          = qp_comms_i2c_cmddata_send_command,
     94     .bulk_command_sequence = qp_comms_i2c_bulk_command_sequence,
     95 };
     96 
     97 #endif // QUANTUM_PAINTER_I2C_ENABLE