// Copyright 2021 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later #ifdef QUANTUM_PAINTER_SPI_ENABLE # include "spi_master.h" # include "qp_comms_spi.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Base SPI support bool qp_comms_spi_init(painter_device_t device) { struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_config_t *comms_config = (struct qp_comms_spi_config_t *)driver->comms_config; // Initialize the SPI peripheral spi_init(); // Set up CS as output high setPinOutput(comms_config->chip_select_pin); writePinHigh(comms_config->chip_select_pin); return true; } bool qp_comms_spi_start(painter_device_t device) { struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_config_t *comms_config = (struct qp_comms_spi_config_t *)driver->comms_config; return spi_start(comms_config->chip_select_pin, comms_config->lsb_first, comms_config->mode, comms_config->divisor); } uint32_t qp_comms_spi_send_data(painter_device_t device, const void *data, uint32_t byte_count) { uint32_t bytes_remaining = byte_count; const uint8_t *p = (const uint8_t *)data; while (bytes_remaining > 0) { uint32_t bytes_this_loop = bytes_remaining < 1024 ? bytes_remaining : 1024; spi_transmit(p, bytes_this_loop); p += bytes_this_loop; bytes_remaining -= bytes_this_loop; } return byte_count - bytes_remaining; } void qp_comms_spi_stop(painter_device_t device) { struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_config_t *comms_config = (struct qp_comms_spi_config_t *)driver->comms_config; spi_stop(); writePinHigh(comms_config->chip_select_pin); } const struct painter_comms_vtable_t spi_comms_vtable = { .comms_init = qp_comms_spi_init, .comms_start = qp_comms_spi_start, .comms_send = qp_comms_spi_send_data, .comms_stop = qp_comms_spi_stop, }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SPI with D/C and RST pins # ifdef QUANTUM_PAINTER_SPI_DC_RESET_ENABLE bool qp_comms_spi_dc_reset_init(painter_device_t device) { if (!qp_comms_spi_init(device)) { return false; } struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config; // Set up D/C as output low, if specified if (comms_config->dc_pin != NO_PIN) { setPinOutput(comms_config->dc_pin); writePinLow(comms_config->dc_pin); } // Set up RST as output, if specified, performing a reset in the process if (comms_config->reset_pin != NO_PIN) { setPinOutput(comms_config->reset_pin); writePinLow(comms_config->reset_pin); wait_ms(20); writePinHigh(comms_config->reset_pin); wait_ms(20); } return true; } uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) { struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config; writePinHigh(comms_config->dc_pin); return qp_comms_spi_send_data(device, data, byte_count); } void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) { struct painter_driver_t * driver = (struct painter_driver_t *)device; struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config; writePinLow(comms_config->dc_pin); spi_write(cmd); } void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { for (size_t i = 0; i < sequence_len;) { uint8_t command = sequence[i]; uint8_t delay = sequence[i + 1]; uint8_t num_bytes = sequence[i + 2]; qp_comms_spi_dc_reset_send_command(device, command); if (num_bytes > 0) { qp_comms_spi_dc_reset_send_data(device, &sequence[i + 3], num_bytes); } if (delay > 0) { wait_ms(delay); } i += (3 + num_bytes); } } const struct painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = { .base = { .comms_init = qp_comms_spi_dc_reset_init, .comms_start = qp_comms_spi_start, .comms_send = qp_comms_spi_dc_reset_send_data, .comms_stop = qp_comms_spi_stop, }, .send_command = qp_comms_spi_dc_reset_send_command, .bulk_command_sequence = qp_comms_spi_dc_reset_bulk_command_sequence, }; # endif // QUANTUM_PAINTER_SPI_DC_RESET_ENABLE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif // QUANTUM_PAINTER_SPI_ENABLE