logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

qp_comms_spi.c (5606B)


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