Browse Source

TFT (plus Hardware SPI) for LPC (#19139)

Victor Oliveira 5 years ago
parent
commit
1a4b82a5d6
No account linked to committer's email address

+ 228
- 24
Marlin/src/HAL/LPC1768/HAL_SPI.cpp View File

@@ -30,7 +30,7 @@
30 30
  */
31 31
 
32 32
 /**
33
- * Hardware SPI and a software SPI implementations are included in this file.
33
+ * Hardware SPI and Software SPI implementations are included in this file.
34 34
  * The hardware SPI runs faster and has higher throughput but is not compatible
35 35
  * with some LCD interfaces/adapters.
36 36
  *
@@ -51,6 +51,10 @@
51 51
 #include "../../inc/MarlinConfig.h"
52 52
 #include <SPI.h>
53 53
 
54
+// Hardware SPI and SPIClass
55
+#include <lpc17xx_pinsel.h>
56
+#include <lpc17xx_clkpwr.h>
57
+
54 58
 // ------------------------
55 59
 // Public functions
56 60
 // ------------------------
@@ -96,12 +100,6 @@
96 100
 
97 101
 #else
98 102
 
99
-  // Hardware SPI
100
-
101
-  #include <lpc17xx_pinsel.h>
102
-  #include <lpc17xx_ssp.h>
103
-  #include <lpc17xx_clkpwr.h>
104
-
105 103
   // decide which HW SPI device to use
106 104
   #ifndef LPC_HW_SPI_DEV
107 105
     #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09)
@@ -114,7 +112,7 @@
114 112
       #endif
115 113
     #endif
116 114
   #endif
117
-  #if (LPC_HW_SPI_DEV == 0)
115
+  #if LPC_HW_SPI_DEV == 0
118 116
     #define LPC_SSPn LPC_SSP0
119 117
   #else
120 118
     #define LPC_SSPn LPC_SSP1
@@ -192,7 +190,7 @@
192 190
     for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
193 191
   }
194 192
 
195
-  static uint8_t spiTransfer(uint8_t b) {
193
+  uint8_t spiTransfer(uint8_t b) {
196 194
     return doio(b);
197 195
   }
198 196
 
@@ -211,30 +209,236 @@
211 209
 
212 210
 #endif // LPC_SOFTWARE_SPI
213 211
 
214
-void SPIClass::begin() { spiBegin(); }
212
+/**
213
+ * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
214
+ */
215
+static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) {
216
+  while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1
217
+  while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ }     // wait until BSY=0
218
+}
219
+
220
+SPIClass::SPIClass(uint8_t device) {
221
+  // Init things specific to each SPI device
222
+  // clock divider setup is a bit of hack, and needs to be improved at a later date.
223
+
224
+  PINSEL_CFG_Type PinCfg;  // data structure to hold init values
225
+  #if BOARD_NR_SPI >= 1
226
+    _settings[0].spi_d = LPC_SSP0;
227
+    // _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
228
+    PinCfg.Funcnum = 2;
229
+    PinCfg.OpenDrain = 0;
230
+    PinCfg.Pinmode = 0;
231
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_SCK_PIN);
232
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_SCK_PIN);
233
+    PINSEL_ConfigPin(&PinCfg);
234
+    SET_OUTPUT(BOARD_SPI1_SCK_PIN);
235
+
236
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MISO_PIN);
237
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MISO_PIN);
238
+    PINSEL_ConfigPin(&PinCfg);
239
+    SET_INPUT(BOARD_SPI1_MISO_PIN);
240
+
241
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MOSI_PIN);
242
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MOSI_PIN);
243
+    PINSEL_ConfigPin(&PinCfg);
244
+    SET_OUTPUT(BOARD_SPI1_MOSI_PIN);
245
+  #endif
246
+
247
+  #if BOARD_NR_SPI >= 2
248
+    _settings[1].spi_d = LPC_SSP1;
249
+    // _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
250
+    PinCfg.Funcnum = 2;
251
+    PinCfg.OpenDrain = 0;
252
+    PinCfg.Pinmode = 0;
253
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_SCK_PIN);
254
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_SCK_PIN);
255
+    PINSEL_ConfigPin(&PinCfg);
256
+    SET_OUTPUT(BOARD_SPI2_SCK_PIN);
257
+
258
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MISO_PIN);
259
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MISO_PIN);
260
+    PINSEL_ConfigPin(&PinCfg);
261
+    SET_INPUT(BOARD_SPI2_MISO_PIN);
262
+
263
+    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MOSI_PIN);
264
+    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MOSI_PIN);
265
+    PINSEL_ConfigPin(&PinCfg);
266
+    SET_OUTPUT(BOARD_SPI2_MOSI_PIN);
267
+  #endif
268
+
269
+  setModule(device);
270
+
271
+  /* Initialize GPDMA controller */
272
+  //TODO: call once in the constructor? or each time?
273
+  GPDMA_Init();
274
+}
275
+
276
+void SPIClass::begin() {
277
+  updateSettings();
278
+  SSP_Cmd(_currentSetting->spi_d, ENABLE);  // start SSP running
279
+}
215 280
 
216 281
 void SPIClass::beginTransaction(const SPISettings &cfg) {
217
-  uint8_t spiRate;
218
-  switch (cfg.spiRate()) {
219
-    case 8000000: spiRate = 0; break;
220
-    case 4000000: spiRate = 1; break;
221
-    case 2000000: spiRate = 2; break;
222
-    case 1000000: spiRate = 3; break;
223
-    case  500000: spiRate = 4; break;
224
-    case  250000: spiRate = 5; break;
225
-    case  125000: spiRate = 6; break;
226
-    default: spiRate = 2; break;
227
-  }
228
-  spiInit(spiRate);
282
+  setBitOrder(cfg.bitOrder);
283
+  setDataMode(cfg.dataMode);
284
+  setDataSize(cfg.dataSize);
285
+  //setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
286
+  begin();
229 287
 }
230 288
 
231
-uint8_t SPIClass::transfer(const uint8_t B) { return spiTransfer(B); }
289
+uint8_t SPIClass::transfer(const uint16_t b) {
290
+  /* send and receive a single byte */
291
+  SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
292
+  SSP_SendData(_currentSetting->spi_d, b);
293
+  waitSpiTxEnd(_currentSetting->spi_d);  // wait for it to finish
294
+  return SSP_ReceiveData(_currentSetting->spi_d);
295
+}
232 296
 
233 297
 uint16_t SPIClass::transfer16(const uint16_t data) {
234 298
   return (transfer((data >> 8) & 0xFF) << 8)
235 299
        | (transfer(data & 0xFF) & 0xFF);
236 300
 }
237 301
 
238
-SPIClass SPI;
302
+void SPIClass::end() {
303
+  // SSP_Cmd(_currentSetting->spi_d, DISABLE);  // stop device or SSP_DeInit?
304
+  SSP_DeInit(_currentSetting->spi_d);
305
+}
306
+
307
+void SPIClass::send(uint8_t data) {
308
+  SSP_SendData(_currentSetting->spi_d, data);
309
+}
310
+
311
+void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
312
+  //TODO: LPC dma can only write 0xFFF bytes at once.
313
+  GPDMA_Channel_CFG_Type GPDMACfg;
314
+
315
+  /* Configure GPDMA channel 0 -------------------------------------------------------------*/
316
+  /* DMA Channel 0 */
317
+  GPDMACfg.ChannelNum = 0;
318
+  // Source memory
319
+  GPDMACfg.SrcMemAddr = (uint32_t)buf;
320
+  // Destination memory - Not used
321
+  GPDMACfg.DstMemAddr = 0;
322
+  // Transfer size
323
+  GPDMACfg.TransferSize = (minc ? length : 1);
324
+  // Transfer width
325
+  GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
326
+  // Transfer type
327
+  GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
328
+  // Source connection - unused
329
+  GPDMACfg.SrcConn = 0;
330
+  // Destination connection
331
+  GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx;
332
+
333
+  GPDMACfg.DMALLI = 0;
334
+
335
+  // Enable dma on SPI
336
+  SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
337
+
338
+  // if minc=false, I'm repeating the same byte 'length' times, as I could not find yet how do GPDMA without memory increment
339
+  do {
340
+    // Setup channel with given parameter
341
+    GPDMA_Setup(&GPDMACfg);
342
+
343
+    // enabled dma
344
+    GPDMA_ChannelCmd(0, ENABLE);
345
+
346
+    // wait data transfer
347
+    while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) { }
348
+
349
+    // clear err and int
350
+    GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
351
+    GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
352
+
353
+    // dma disable
354
+    GPDMA_ChannelCmd(0, DISABLE);
355
+
356
+    --length;
357
+  } while (!minc && length > 0);
358
+
359
+  waitSpiTxEnd(_currentSetting->spi_d);
360
+
361
+  SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
362
+}
363
+
364
+uint16_t SPIClass::read() {
365
+  return SSP_ReceiveData(_currentSetting->spi_d);
366
+}
367
+
368
+void SPIClass::read(uint8_t *buf, uint32_t len) {
369
+  for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
370
+}
371
+
372
+void SPIClass::setClock(uint32_t clock) {
373
+  _currentSetting->clock = clock;
374
+}
375
+
376
+void SPIClass::setModule(uint8_t device) {
377
+  _currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
378
+}
379
+
380
+void SPIClass::setBitOrder(uint8_t bitOrder) {
381
+  _currentSetting->bitOrder = bitOrder;
382
+}
383
+
384
+void SPIClass::setDataMode(uint8_t dataMode) {
385
+  _currentSetting->dataSize = dataMode;
386
+}
387
+
388
+void SPIClass::setDataSize(uint32_t ds) {
389
+  _currentSetting->dataSize = ds;
390
+}
391
+
392
+/**
393
+ * Set up/tear down
394
+ */
395
+void SPIClass::updateSettings() {
396
+  //SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
397
+
398
+  // divide PCLK by 2 for SSP0
399
+  CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
400
+
401
+  SSP_CFG_Type HW_SPI_init; // data structure to hold init values
402
+  SSP_ConfigStructInit(&HW_SPI_init);  // set values for SPI mode
403
+  HW_SPI_init.ClockRate = _currentSetting->clock;
404
+  HW_SPI_init.Databit = _currentSetting->dataSize;
405
+
406
+  /**
407
+   * SPI Mode  CPOL  CPHA  Shift SCK-edge  Capture SCK-edge
408
+   * 0       0     0     Falling     Rising
409
+   * 1       0     1     Rising      Falling
410
+   * 2       1     0     Rising      Falling
411
+   * 3       1     1     Falling     Rising
412
+   */
413
+  switch (_currentSetting->dataMode) {
414
+    case SPI_MODE0:
415
+      HW_SPI_init.CPHA = SSP_CPHA_FIRST;
416
+	    HW_SPI_init.CPOL = SSP_CPOL_HI;
417
+      break;
418
+    case SPI_MODE1:
419
+      HW_SPI_init.CPHA = SSP_CPHA_SECOND;
420
+	    HW_SPI_init.CPOL = SSP_CPOL_HI;
421
+      break;
422
+    case SPI_MODE2:
423
+      HW_SPI_init.CPHA = SSP_CPHA_FIRST;
424
+	    HW_SPI_init.CPOL = SSP_CPOL_LO;
425
+      break;
426
+    case SPI_MODE3:
427
+      HW_SPI_init.CPHA = SSP_CPHA_SECOND;
428
+	    HW_SPI_init.CPOL = SSP_CPOL_LO;
429
+      break;
430
+    default:
431
+      break;
432
+  }
433
+
434
+  // TODO: handle bitOrder
435
+  SSP_Init(_currentSetting->spi_d, &HW_SPI_init);  // puts the values into the proper bits in the SSP0 registers
436
+}
437
+
438
+#if MISO_PIN == BOARD_SPI1_MISO_PIN
439
+  SPIClass SPI(1);
440
+#elif MISO_PIN == BOARD_SPI2_MISO_PIN
441
+  SPIClass SPI(2);
442
+#endif
239 443
 
240 444
 #endif // TARGET_LPC1768

+ 9
- 2
Marlin/src/HAL/LPC1768/inc/Conditionals_LCD.h View File

@@ -21,6 +21,13 @@
21 21
  */
22 22
 #pragma once
23 23
 
24
-#if HAS_SPI_TFT || HAS_FSMC_TFT
25
-  #error "Sorry! TFT displays are not available for HAL/LPC1768."
24
+#if HAS_FSMC_TFT
25
+  #error "Sorry! FSMC TFT displays are not current available for HAL/LPC1768."
26
+#endif
27
+
28
+// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
29
+#if ENABLED(TOUCH_SCREEN) && !HAS_GRAPHICAL_TFT
30
+  #undef TOUCH_SCREEN
31
+  #undef TOUCH_SCREEN_CALIBRATION
32
+  #define HAS_TOUCH_XPT2046 1
26 33
 #endif

+ 127
- 13
Marlin/src/HAL/LPC1768/include/SPI.h View File

@@ -24,25 +24,139 @@
24 24
 #include "../../shared/HAL_SPI.h"
25 25
 
26 26
 #include <stdint.h>
27
+#include <lpc17xx_ssp.h>
28
+#include <lpc17xx_gpdma.h>
27 29
 
28
-#define MSBFIRST 1
29
-#define SPI_MODE3 0
30
+//#define MSBFIRST 1
31
+
32
+#define SPI_MODE0 0
33
+#define SPI_MODE1 1
34
+#define SPI_MODE2 2
35
+#define SPI_MODE3 3
36
+
37
+#define DATA_SIZE_8BIT SSP_DATABIT_8
38
+#define DATA_SIZE_16BIT SSP_DATABIT_16
39
+
40
+#define SPI_CLOCK_DIV2   8333333 //(SCR:  2)  desired: 8,000,000  actual: 8,333,333  +4.2%  SPI_FULL_SPEED
41
+#define SPI_CLOCK_DIV4   4166667 //(SCR:  5)  desired: 4,000,000  actual: 4,166,667  +4.2%  SPI_HALF_SPEED
42
+#define SPI_CLOCK_DIV8   2083333 //(SCR: 11)  desired: 2,000,000  actual: 2,083,333  +4.2%  SPI_QUARTER_SPEED
43
+#define SPI_CLOCK_DIV16  1000000 //(SCR: 24)  desired: 1,000,000  actual: 1,000,000         SPI_EIGHTH_SPEED
44
+#define SPI_CLOCK_DIV32   500000 //(SCR: 49)  desired:   500,000  actual:   500,000         SPI_SPEED_5
45
+#define SPI_CLOCK_DIV64   250000 //(SCR: 99)  desired:   250,000  actual:   250,000         SPI_SPEED_6
46
+#define SPI_CLOCK_DIV128  125000 //(SCR:199)  desired:   125,000  actual:   125,000         Default from HAL.h
47
+
48
+#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
49
+
50
+#define BOARD_NR_SPI 2
51
+
52
+//#define BOARD_SPI1_NSS_PIN      PA4 ?!
53
+#define BOARD_SPI1_SCK_PIN      P0_15
54
+#define BOARD_SPI1_MISO_PIN     P0_17
55
+#define BOARD_SPI1_MOSI_PIN     P0_18
56
+
57
+//#define BOARD_SPI2_NSS_PIN      PB12 ?!
58
+#define BOARD_SPI2_SCK_PIN      P0_07
59
+#define BOARD_SPI2_MISO_PIN     P0_08
60
+#define BOARD_SPI2_MOSI_PIN     P0_09
30 61
 
31 62
 class SPISettings {
32
-  public:
33
-    SPISettings(uint32_t speed, int, int) : spi_speed(speed) {};
34
-    uint32_t spiRate() const { return spi_speed; }
35
-  private:
36
-    uint32_t spi_speed;
63
+public:
64
+  SPISettings(uint32_t speed, int, int) : spi_speed(speed) {};
65
+  SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
66
+    if (__builtin_constant_p(inClock))
67
+      init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
68
+    else
69
+      init_MightInline(inClock, inBitOrder, inDataMode, inDataSize);
70
+  }
71
+  SPISettings() {
72
+    init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
73
+  }
74
+
75
+  uint32_t spiRate() const { return spi_speed; }
76
+
77
+private:
78
+  void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
79
+    init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
80
+  }
81
+  void init_AlwaysInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) {
82
+    clock    = inClock;
83
+    bitOrder = inBitOrder;
84
+    dataMode = inDataMode;
85
+    dataSize = inDataSize;
86
+  }
87
+
88
+  uint32_t spi_speed;
89
+  uint32_t clock;
90
+  uint32_t dataSize;
91
+  //uint32_t clockDivider;
92
+  uint8_t bitOrder;
93
+  uint8_t dataMode;
94
+  LPC_SSP_TypeDef *spi_d;
95
+
96
+  friend class SPIClass;
37 97
 };
38 98
 
99
+/**
100
+ * @brief Wirish SPI interface.
101
+ *
102
+ * This is the same interface is available across HAL
103
+ *
104
+ * This implementation uses software slave management, so the caller
105
+ * is responsible for controlling the slave select line.
106
+ */
39 107
 class SPIClass {
40
-  public:
41
-    void begin();
42
-    void beginTransaction(const SPISettings&);
43
-    void endTransaction() {};
44
-    uint8_t transfer(uint8_t data);
45
-    uint16_t transfer16(uint16_t data);
108
+public:
109
+  /**
110
+   * @param spiPortNumber Number of the SPI port to manage.
111
+   */
112
+  SPIClass(uint8_t spiPortNumber);
113
+
114
+  /**
115
+   * Select and configure the current selected SPI device to use
116
+   */
117
+  void begin();
118
+
119
+  /**
120
+   * Disable the current SPI device
121
+   */
122
+  void end();
123
+
124
+  void beginTransaction(const SPISettings&);
125
+  void endTransaction() {};
126
+
127
+  // Transfer using 1 "Data Size"
128
+  uint8_t transfer(uint16_t data);
129
+  // Transfer 2 bytes in 8 bit mode
130
+  uint16_t transfer16(uint16_t data);
131
+
132
+  void send(uint8_t data);
133
+
134
+  uint16_t read();
135
+  void read(uint8_t *buf, uint32_t len);
136
+
137
+  void dmaSend(void *buf, uint16_t length, bool minc);
138
+
139
+  /**
140
+   * @brief Sets the number of the SPI peripheral to be used by
141
+   *        this HardwareSPI instance.
142
+   *
143
+   * @param spi_num Number of the SPI port. 1-2 in low density devices
144
+   *     or 1-3 in high density devices.
145
+   */
146
+  void setModule(uint8_t device);
147
+
148
+  void setClock(uint32_t clock);
149
+  void setBitOrder(uint8_t bitOrder);
150
+  void setDataMode(uint8_t dataMode);
151
+  void setDataSize(uint32_t ds);
152
+
153
+  inline uint32_t getDataSize() { return _currentSetting->dataSize; }
154
+
155
+private:
156
+  SPISettings _settings[BOARD_NR_SPI];
157
+  SPISettings *_currentSetting;
158
+
159
+  void updateSettings();
46 160
 };
47 161
 
48 162
 extern SPIClass SPI;

+ 153
- 0
Marlin/src/HAL/LPC1768/tft/tft_spi.cpp View File

@@ -0,0 +1,153 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../inc/MarlinConfig.h"
24
+
25
+#if HAS_SPI_TFT
26
+
27
+#include "tft_spi.h"
28
+
29
+//TFT_SPI tft;
30
+
31
+SPIClass TFT_SPI::SPIx(1);
32
+
33
+#define TFT_CS_H  WRITE(TFT_CS_PIN, HIGH)
34
+#define TFT_CS_L  WRITE(TFT_CS_PIN, LOW)
35
+
36
+#define TFT_DC_H  WRITE(TFT_DC_PIN, HIGH)
37
+#define TFT_DC_L  WRITE(TFT_DC_PIN, LOW)
38
+
39
+#define TFT_RST_H WRITE(TFT_RESET_PIN, HIGH)
40
+#define TFT_RST_L WRITE(TFT_RESET_PIN, LOW)
41
+
42
+#define TFT_BLK_H WRITE(TFT_BACKLIGHT_PIN, HIGH)
43
+#define TFT_BLK_L WRITE(TFT_BACKLIGHT_PIN, LOW)
44
+
45
+void TFT_SPI::Init() {
46
+  #if PIN_EXISTS(TFT_RESET)
47
+    SET_OUTPUT(TFT_RESET_PIN);
48
+    TFT_RST_H;
49
+    delay(100);
50
+  #endif
51
+
52
+  #if PIN_EXISTS(TFT_BACKLIGHT)
53
+    SET_OUTPUT(TFT_BACKLIGHT_PIN);
54
+    TFT_BLK_H;
55
+  #endif
56
+
57
+  SET_OUTPUT(TFT_DC_PIN);
58
+  SET_OUTPUT(TFT_CS_PIN);
59
+
60
+  TFT_DC_H;
61
+  TFT_CS_H;
62
+
63
+  /**
64
+   * STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
65
+   * STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
66
+   * so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
67
+   */
68
+  #if 0
69
+    #if SPI_DEVICE == 1
70
+     #define SPI_CLOCK_MAX SPI_CLOCK_DIV4
71
+    #else
72
+     #define SPI_CLOCK_MAX SPI_CLOCK_DIV2
73
+    #endif
74
+    uint8_t  clock;
75
+    uint8_t spiRate = SPI_FULL_SPEED;
76
+    switch (spiRate) {
77
+     case SPI_FULL_SPEED:    clock = SPI_CLOCK_MAX ;  break;
78
+     case SPI_HALF_SPEED:    clock = SPI_CLOCK_DIV4 ; break;
79
+     case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break;
80
+     case SPI_EIGHTH_SPEED:  clock = SPI_CLOCK_DIV16; break;
81
+     case SPI_SPEED_5:       clock = SPI_CLOCK_DIV32; break;
82
+     case SPI_SPEED_6:       clock = SPI_CLOCK_DIV64; break;
83
+     default:                clock = SPI_CLOCK_DIV2;  // Default from the SPI library
84
+    }
85
+  #endif
86
+
87
+  #if TFT_MISO_PIN == BOARD_SPI1_MISO_PIN
88
+    SPIx.setModule(1);
89
+  #elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN
90
+    SPIx.setModule(2);
91
+  #endif
92
+  SPIx.setClock(SPI_CLOCK_MAX);
93
+  SPIx.setBitOrder(MSBFIRST);
94
+  SPIx.setDataMode(SPI_MODE0);
95
+}
96
+
97
+void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
98
+  SPIx.setDataSize(DataSize);
99
+  SPIx.begin();
100
+  TFT_CS_L;
101
+}
102
+
103
+uint32_t TFT_SPI::GetID() {
104
+  uint32_t id;
105
+  id = ReadID(LCD_READ_ID);
106
+  if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
107
+    id = ReadID(LCD_READ_ID4);
108
+  return id;
109
+}
110
+
111
+uint32_t TFT_SPI::ReadID(uint16_t Reg) {
112
+  uint32_t data = 0;
113
+
114
+  #if PIN_EXISTS(TFT_MISO)
115
+    uint8_t d = 0;
116
+    SPIx.setDataSize(DATASIZE_8BIT);
117
+    SPIx.setClock(SPI_CLOCK_DIV64);
118
+    SPIx.begin();
119
+    TFT_CS_L;
120
+    WriteReg(Reg);
121
+
122
+    LOOP_L_N(i, 4) {
123
+      SPIx.read((uint8_t*)&d, 1);
124
+      data = (data << 8) | d;
125
+    }
126
+
127
+    DataTransferEnd();
128
+    SPIx.setClock(SPI_CLOCK_MAX);
129
+  #endif
130
+
131
+  return data >> 7;
132
+}
133
+
134
+bool TFT_SPI::isBusy() {
135
+  return false;
136
+}
137
+
138
+void TFT_SPI::Abort() {
139
+  DataTransferEnd();
140
+}
141
+
142
+void TFT_SPI::Transmit(uint16_t Data) {
143
+  SPIx.transfer(Data);
144
+}
145
+
146
+void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
147
+  DataTransferBegin(DATASIZE_16BIT); //16
148
+  TFT_DC_H;
149
+  SPIx.dmaSend(Data, Count, MemoryIncrease);
150
+  DataTransferEnd();
151
+}
152
+
153
+#endif // HAS_SPI_TFT

+ 77
- 0
Marlin/src/HAL/LPC1768/tft/tft_spi.h View File

@@ -0,0 +1,77 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../../../inc/MarlinConfig.h"
25
+
26
+#include <SPI.h>
27
+#include <lpc17xx_ssp.h>
28
+// #include <lpc17xx_gpdma.h>
29
+
30
+#ifndef LCD_READ_ID
31
+  #define LCD_READ_ID  0x04   // Read display identification information (0xD3 on ILI9341)
32
+#endif
33
+#ifndef LCD_READ_ID4
34
+  #define LCD_READ_ID4 0xD3   // Read display identification information (0xD3 on ILI9341)
35
+#endif
36
+
37
+#define DATASIZE_8BIT    SSP_DATABIT_8
38
+#define DATASIZE_16BIT   SSP_DATABIT_16
39
+#define TFT_IO TFT_SPI
40
+
41
+#define DMA_MINC_ENABLE 1
42
+#define DMA_MINC_DISABLE 0
43
+
44
+class TFT_SPI {
45
+private:
46
+  static uint32_t ReadID(uint16_t Reg);
47
+  static void Transmit(uint16_t Data);
48
+  static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
49
+
50
+public:
51
+  static SPIClass SPIx;
52
+
53
+  static void Init();
54
+  static uint32_t GetID();
55
+  static bool isBusy();
56
+  static void Abort();
57
+
58
+  static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
59
+  static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); };
60
+  static void DataTransferAbort();
61
+
62
+  static void WriteData(uint16_t Data) { Transmit(Data); }
63
+  static void WriteReg(uint16_t Reg) { OUT_WRITE(TFT_A0_PIN, LOW); Transmit(Reg); OUT_WRITE(TFT_A0_PIN, HIGH); }
64
+
65
+  static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
66
+  // static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
67
+  static void WriteMultiple(uint16_t Color, uint32_t Count) {
68
+    static uint16_t Data; Data = Color;
69
+    //LPC dma can only write 0xFFF bytes at once.
70
+    #define MAX_DMA_SIZE (0xFFF - 1)
71
+    while (Count > 0) {
72
+      TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count);
73
+      Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0;
74
+    }
75
+    #undef MAX_DMA_SIZE
76
+  }
77
+};

+ 129
- 0
Marlin/src/HAL/LPC1768/tft/xpt2046.cpp View File

@@ -0,0 +1,129 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
+ *
18
+ */
19
+
20
+#include "../../../inc/MarlinConfig.h"
21
+
22
+#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
23
+
24
+#include "xpt2046.h"
25
+#include <SPI.h>
26
+
27
+uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
28
+
29
+#if ENABLED(TOUCH_BUTTONS_HW_SPI)
30
+  #include <SPI.h>
31
+
32
+  SPIClass XPT2046::SPIx(TOUCH_BUTTONS_HW_SPI_DEVICE);
33
+
34
+  static void touch_spi_init(uint8_t spiRate) {
35
+    XPT2046::SPIx.setModule(TOUCH_BUTTONS_HW_SPI_DEVICE);
36
+    XPT2046::SPIx.setClock(SPI_CLOCK_DIV128);
37
+    XPT2046::SPIx.setBitOrder(MSBFIRST);
38
+    XPT2046::SPIx.setDataMode(SPI_MODE0);
39
+    XPT2046::SPIx.setDataSize(DATA_SIZE_8BIT);
40
+  }
41
+#endif
42
+
43
+void XPT2046::Init() {
44
+  SET_INPUT(TOUCH_MISO_PIN);
45
+  SET_OUTPUT(TOUCH_MOSI_PIN);
46
+  SET_OUTPUT(TOUCH_SCK_PIN);
47
+  OUT_WRITE(TOUCH_CS_PIN, HIGH);
48
+
49
+  #if PIN_EXISTS(TOUCH_INT)
50
+    // Optional Pendrive interrupt pin
51
+    SET_INPUT(TOUCH_INT_PIN);
52
+  #endif
53
+
54
+  TERN_(TOUCH_BUTTONS_HW_SPI, touch_spi_init(SPI_SPEED_6));
55
+
56
+  // Read once to enable pendrive status pin
57
+  getRawData(XPT2046_X);
58
+}
59
+
60
+bool XPT2046::isTouched() {
61
+  return isBusy() ? false : (
62
+    #if PIN_EXISTS(TOUCH_INT)
63
+      READ(TOUCH_INT_PIN) != HIGH
64
+    #else
65
+      getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
66
+    #endif
67
+  );
68
+}
69
+
70
+bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
71
+  if (isBusy()) return false;
72
+  if (!isTouched()) return false;
73
+  *x = getRawData(XPT2046_X);
74
+  *y = getRawData(XPT2046_Y);
75
+  SERIAL_ECHOLNPAIR("X: ", *x, ", Y: ", *y);
76
+  return isTouched();
77
+}
78
+
79
+uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
80
+  uint16_t data[3];
81
+
82
+  DataTransferBegin();
83
+  TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.begin());
84
+
85
+  for (uint16_t i = 0; i < 3 ; i++) {
86
+    IO(coordinate);
87
+    data[i] = (IO() << 4) | (IO() >> 4);
88
+  }
89
+
90
+  TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.end());
91
+  DataTransferEnd();
92
+
93
+  uint16_t delta01 = delta(data[0], data[1]),
94
+           delta02 = delta(data[0], data[2]),
95
+           delta12 = delta(data[1], data[2]);
96
+
97
+  if (delta01 > delta02 || delta01 > delta12)
98
+    data[delta02 > delta12 ? 0 : 1] = data[2];
99
+
100
+  return (data[0] + data[1]) >> 1;
101
+}
102
+
103
+uint16_t XPT2046::IO(uint16_t data) {
104
+  return TERN(TOUCH_BUTTONS_HW_SPI, HardwareIO, SoftwareIO)(data);
105
+}
106
+
107
+extern uint8_t spiTransfer(uint8_t b);
108
+
109
+#if ENABLED(TOUCH_BUTTONS_HW_SPI)
110
+  uint16_t XPT2046::HardwareIO(uint16_t data) {
111
+    return SPIx.transfer(data & 0xFF);
112
+  }
113
+#endif
114
+
115
+uint16_t XPT2046::SoftwareIO(uint16_t data) {
116
+  uint16_t result = 0;
117
+
118
+  for (uint8_t j = 0x80; j; j >>= 1) {
119
+    WRITE(TOUCH_SCK_PIN, LOW);
120
+    WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW);
121
+    if (READ(TOUCH_MISO_PIN)) result |= j;
122
+    WRITE(TOUCH_SCK_PIN, HIGH);
123
+  }
124
+  WRITE(TOUCH_SCK_PIN, LOW);
125
+
126
+  return result;
127
+}
128
+
129
+#endif // HAS_TFT_XPT2046

+ 80
- 0
Marlin/src/HAL/LPC1768/tft/xpt2046.h View File

@@ -0,0 +1,80 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
+ *
18
+ */
19
+#pragma once
20
+
21
+#include "../../../inc/MarlinConfig.h"
22
+
23
+#if ENABLED(TOUCH_BUTTONS_HW_SPI)
24
+  #include <SPI.h>
25
+#endif
26
+
27
+#ifndef TOUCH_MISO_PIN
28
+  #define TOUCH_MISO_PIN MISO_PIN
29
+#endif
30
+#ifndef TOUCH_MOSI_PIN
31
+  #define TOUCH_MOSI_PIN MOSI_PIN
32
+#endif
33
+#ifndef TOUCH_SCK_PIN
34
+  #define TOUCH_SCK_PIN  SCK_PIN
35
+#endif
36
+#ifndef TOUCH_CS_PIN
37
+  #define TOUCH_CS_PIN   CS_PIN
38
+#endif
39
+#ifndef TOUCH_INT_PIN
40
+  #define TOUCH_INT_PIN  -1
41
+#endif
42
+
43
+#define XPT2046_DFR_MODE        0x00
44
+#define XPT2046_SER_MODE        0x04
45
+#define XPT2046_CONTROL         0x80
46
+
47
+enum XPTCoordinate : uint8_t {
48
+  XPT2046_X  = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE,
49
+  XPT2046_Y  = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE,
50
+  XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE,
51
+  XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
52
+};
53
+
54
+#if !defined(XPT2046_Z1_THRESHOLD)
55
+  #define XPT2046_Z1_THRESHOLD 10
56
+#endif
57
+
58
+class XPT2046 {
59
+private:
60
+  static bool isBusy() { return false; }
61
+
62
+  static uint16_t getRawData(const XPTCoordinate coordinate);
63
+  static bool isTouched();
64
+
65
+  static inline void DataTransferBegin() { WRITE(TOUCH_CS_PIN, LOW); };
66
+  static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); };
67
+  #if ENABLED(TOUCH_BUTTONS_HW_SPI)
68
+    static uint16_t HardwareIO(uint16_t data);
69
+  #endif
70
+  static uint16_t SoftwareIO(uint16_t data);
71
+  static uint16_t IO(uint16_t data = 0);
72
+
73
+public:
74
+  #if ENABLED(TOUCH_BUTTONS_HW_SPI)
75
+    static SPIClass SPIx;
76
+  #endif
77
+
78
+  static void Init();
79
+  static bool getRawPoint(int16_t *x, int16_t *y);
80
+};

+ 4
- 6
Marlin/src/lcd/dogm/HAL_LCD_com_defines.h View File

@@ -82,11 +82,6 @@
82 82
 
83 83
   #define U8G_COM_SSD_I2C_HAL         u8g_com_arduino_ssd_i2c_fn
84 84
 
85
-  #if EITHER(FSMC_GRAPHICAL_TFT, SPI_GRAPHICAL_TFT)
86
-    uint8_t u8g_com_stm32duino_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
87
-    #define U8G_COM_HAL_TFT_FN       u8g_com_stm32duino_tft_fn
88
-  #endif
89
-
90 85
 #elif defined(TARGET_LPC1768)
91 86
 
92 87
   uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
@@ -117,6 +112,9 @@
117 112
 #ifndef U8G_COM_SSD_I2C_HAL
118 113
   #define U8G_COM_SSD_I2C_HAL       u8g_com_null_fn
119 114
 #endif
120
-#ifndef U8G_COM_HAL_TFT_FN
115
+#if EITHER(FSMC_GRAPHICAL_TFT, SPI_GRAPHICAL_TFT)
116
+  uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
117
+  #define U8G_COM_HAL_TFT_FN       u8g_com_hal_tft_fn
118
+#else
121 119
   #define U8G_COM_HAL_TFT_FN       u8g_com_null_fn
122 120
 #endif

+ 2
- 2
Marlin/src/lcd/dogm/u8g_dev_tft_320x240_upscale_from_128x64.cpp View File

@@ -760,7 +760,7 @@ uint8_t u8g_dev_tft_320x240_upscale_from_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, u
760 760
 
761 761
 static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
762 762
 
763
-uint8_t u8g_com_stm32duino_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
763
+uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
764 764
   if (msgInitCount) {
765 765
     if (msg == U8G_COM_MSG_INIT) msgInitCount--;
766 766
     if (msgInitCount) return -1;
@@ -801,7 +801,7 @@ uint8_t u8g_com_stm32duino_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
801 801
       break;
802 802
 
803 803
     case U8G_COM_MSG_WRITE_SEQ:
804
-      tftio.DataTransferBegin(DATASIZE_8BIT);
804
+      tftio.DataTransferBegin(DATASIZE_16BIT);
805 805
       for (uint8_t i = 0; i < arg_val; i += 2)
806 806
         tftio.WriteData(*(uint16_t *)(((uint32_t)arg_ptr) + i));
807 807
       tftio.DataTransferEnd();

+ 32
- 0
Marlin/src/pins/lpc1768/pins_BTT_SKR_V1_4.h View File

@@ -274,6 +274,38 @@
274 274
     #define FORCE_SOFT_SPI
275 275
     #define LCD_BACKLIGHT_PIN              -1
276 276
 
277
+  #elif HAS_SPI_TFT                               // Config for Classic UI (emulated DOGM) and Color UI
278
+    #define SS_PIN                         -1
279
+    //#define ONBOARD_SD_CS_PIN            -1
280
+
281
+    #define TFT_CS_PIN                     P1_22
282
+    #define TFT_A0_PIN                     P1_23
283
+    #define TFT_DC_PIN                     P1_23
284
+    #define TFT_MISO_PIN                   P0_17
285
+    #define TFT_BACKLIGHT_PIN              P1_18
286
+    #define TFT_RESET_PIN                  P1_19
287
+
288
+    #define LPC_HW_SPI_DEV                     0
289
+    #define LCD_USE_DMA_SPI
290
+
291
+    #define TOUCH_INT_PIN                  P1_21
292
+    #define TOUCH_CS_PIN                   P1_20
293
+    #define TOUCH_BUTTONS_HW_SPI
294
+    #define TOUCH_BUTTONS_HW_SPI_DEVICE        1
295
+
296
+    #ifndef GRAPHICAL_TFT_UPSCALE
297
+      #define GRAPHICAL_TFT_UPSCALE            3
298
+    #endif
299
+
300
+    // SPI 1
301
+    #define SCK_PIN                        P0_15
302
+    #define MISO_PIN                       P0_17
303
+    #define MOSI_PIN                       P0_18
304
+
305
+    // Disable any LCD related PINs config
306
+    #define LCD_PINS_ENABLE                -1
307
+    #define LCD_PINS_RS                    -1
308
+
277 309
   #else
278 310
 
279 311
     #define BTN_ENC                        P0_28  // (58) open-drain

+ 19
- 0
Marlin/src/pins/pinsDebug_list.h View File

@@ -1421,3 +1421,22 @@
1421 1421
 #if PIN_EXISTS(ESP_WIFI_MODULE_GPIO2)
1422 1422
   REPORT_NAME_DIGITAL(__LINE__, ESP_WIFI_MODULE_GPIO2_PIN)
1423 1423
 #endif
1424
+// TFT PINS
1425
+#if PIN_EXISTS(TFT_CS)
1426
+  REPORT_NAME_DIGITAL(__LINE__, TFT_CS_PIN)
1427
+#endif
1428
+#if PIN_EXISTS(TFT_A0)
1429
+  REPORT_NAME_DIGITAL(__LINE__, TFT_A0_PIN)
1430
+#endif
1431
+#if PIN_EXISTS(TFT_DC)
1432
+  REPORT_NAME_DIGITAL(__LINE__, TFT_DC_PIN)
1433
+#endif
1434
+#if PIN_EXISTS(TFT_MISO)
1435
+  REPORT_NAME_DIGITAL(__LINE__, TFT_MISO_PIN)
1436
+#endif
1437
+#if PIN_EXISTS(TFT_BACKLIGHT)
1438
+  REPORT_NAME_DIGITAL(__LINE__, TFT_BACKLIGHT_PIN)
1439
+#endif
1440
+#if PIN_EXISTS(TFT_RESET)
1441
+  REPORT_NAME_DIGITAL(__LINE__, TFT_RESET_PIN)
1442
+#endif

Loading…
Cancel
Save