You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
5.1 KiB

  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. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  10. struct qp_comms_spi_config_t *comms_config = (struct qp_comms_spi_config_t *)driver->comms_config;
  11. // Initialize the SPI peripheral
  12. spi_init();
  13. // Set up CS as output high
  14. setPinOutput(comms_config->chip_select_pin);
  15. writePinHigh(comms_config->chip_select_pin);
  16. return true;
  17. }
  18. bool qp_comms_spi_start(painter_device_t device) {
  19. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  20. struct qp_comms_spi_config_t *comms_config = (struct 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. while (bytes_remaining > 0) {
  27. uint32_t bytes_this_loop = bytes_remaining < 1024 ? bytes_remaining : 1024;
  28. spi_transmit(p, bytes_this_loop);
  29. p += bytes_this_loop;
  30. bytes_remaining -= bytes_this_loop;
  31. }
  32. return byte_count - bytes_remaining;
  33. }
  34. void qp_comms_spi_stop(painter_device_t device) {
  35. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  36. struct qp_comms_spi_config_t *comms_config = (struct qp_comms_spi_config_t *)driver->comms_config;
  37. spi_stop();
  38. writePinHigh(comms_config->chip_select_pin);
  39. }
  40. const struct painter_comms_vtable_t spi_comms_vtable = {
  41. .comms_init = qp_comms_spi_init,
  42. .comms_start = qp_comms_spi_start,
  43. .comms_send = qp_comms_spi_send_data,
  44. .comms_stop = qp_comms_spi_stop,
  45. };
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  47. // SPI with D/C and RST pins
  48. # ifdef QUANTUM_PAINTER_SPI_DC_RESET_ENABLE
  49. bool qp_comms_spi_dc_reset_init(painter_device_t device) {
  50. if (!qp_comms_spi_init(device)) {
  51. return false;
  52. }
  53. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  54. struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config;
  55. // Set up D/C as output low, if specified
  56. if (comms_config->dc_pin != NO_PIN) {
  57. setPinOutput(comms_config->dc_pin);
  58. writePinLow(comms_config->dc_pin);
  59. }
  60. // Set up RST as output, if specified, performing a reset in the process
  61. if (comms_config->reset_pin != NO_PIN) {
  62. setPinOutput(comms_config->reset_pin);
  63. writePinLow(comms_config->reset_pin);
  64. wait_ms(20);
  65. writePinHigh(comms_config->reset_pin);
  66. wait_ms(20);
  67. }
  68. return true;
  69. }
  70. uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
  71. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  72. struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config;
  73. writePinHigh(comms_config->dc_pin);
  74. return qp_comms_spi_send_data(device, data, byte_count);
  75. }
  76. void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) {
  77. struct painter_driver_t * driver = (struct painter_driver_t *)device;
  78. struct qp_comms_spi_dc_reset_config_t *comms_config = (struct qp_comms_spi_dc_reset_config_t *)driver->comms_config;
  79. writePinLow(comms_config->dc_pin);
  80. spi_write(cmd);
  81. }
  82. void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
  83. for (size_t i = 0; i < sequence_len;) {
  84. uint8_t command = sequence[i];
  85. uint8_t delay = sequence[i + 1];
  86. uint8_t num_bytes = sequence[i + 2];
  87. qp_comms_spi_dc_reset_send_command(device, command);
  88. if (num_bytes > 0) {
  89. qp_comms_spi_dc_reset_send_data(device, &sequence[i + 3], num_bytes);
  90. }
  91. if (delay > 0) {
  92. wait_ms(delay);
  93. }
  94. i += (3 + num_bytes);
  95. }
  96. }
  97. const struct painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = {
  98. .base =
  99. {
  100. .comms_init = qp_comms_spi_dc_reset_init,
  101. .comms_start = qp_comms_spi_start,
  102. .comms_send = qp_comms_spi_dc_reset_send_data,
  103. .comms_stop = qp_comms_spi_stop,
  104. },
  105. .send_command = qp_comms_spi_dc_reset_send_command,
  106. .bulk_command_sequence = qp_comms_spi_dc_reset_bulk_command_sequence,
  107. };
  108. # endif // QUANTUM_PAINTER_SPI_DC_RESET_ENABLE
  109. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  110. #endif // QUANTUM_PAINTER_SPI_ENABLE