TFT (plus Hardware SPI) for LPC (#19139)
This commit is contained in:
		| @@ -30,7 +30,7 @@ | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Hardware SPI and a software SPI implementations are included in this file. | ||||
|  * Hardware SPI and Software SPI implementations are included in this file. | ||||
|  * The hardware SPI runs faster and has higher throughput but is not compatible | ||||
|  * with some LCD interfaces/adapters. | ||||
|  * | ||||
| @@ -51,6 +51,10 @@ | ||||
| #include "../../inc/MarlinConfig.h" | ||||
| #include <SPI.h> | ||||
|  | ||||
| // Hardware SPI and SPIClass | ||||
| #include <lpc17xx_pinsel.h> | ||||
| #include <lpc17xx_clkpwr.h> | ||||
|  | ||||
| // ------------------------ | ||||
| // Public functions | ||||
| // ------------------------ | ||||
| @@ -96,12 +100,6 @@ | ||||
|  | ||||
| #else | ||||
|  | ||||
|   // Hardware SPI | ||||
|  | ||||
|   #include <lpc17xx_pinsel.h> | ||||
|   #include <lpc17xx_ssp.h> | ||||
|   #include <lpc17xx_clkpwr.h> | ||||
|  | ||||
|   // decide which HW SPI device to use | ||||
|   #ifndef LPC_HW_SPI_DEV | ||||
|     #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09) | ||||
| @@ -114,7 +112,7 @@ | ||||
|       #endif | ||||
|     #endif | ||||
|   #endif | ||||
|   #if (LPC_HW_SPI_DEV == 0) | ||||
|   #if LPC_HW_SPI_DEV == 0 | ||||
|     #define LPC_SSPn LPC_SSP0 | ||||
|   #else | ||||
|     #define LPC_SSPn LPC_SSP1 | ||||
| @@ -192,7 +190,7 @@ | ||||
|     for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF); | ||||
|   } | ||||
|  | ||||
|   static uint8_t spiTransfer(uint8_t b) { | ||||
|   uint8_t spiTransfer(uint8_t b) { | ||||
|     return doio(b); | ||||
|   } | ||||
|  | ||||
| @@ -211,30 +209,236 @@ | ||||
|  | ||||
| #endif // LPC_SOFTWARE_SPI | ||||
|  | ||||
| void SPIClass::begin() { spiBegin(); } | ||||
|  | ||||
| void SPIClass::beginTransaction(const SPISettings &cfg) { | ||||
|   uint8_t spiRate; | ||||
|   switch (cfg.spiRate()) { | ||||
|     case 8000000: spiRate = 0; break; | ||||
|     case 4000000: spiRate = 1; break; | ||||
|     case 2000000: spiRate = 2; break; | ||||
|     case 1000000: spiRate = 3; break; | ||||
|     case  500000: spiRate = 4; break; | ||||
|     case  250000: spiRate = 5; break; | ||||
|     case  125000: spiRate = 6; break; | ||||
|     default: spiRate = 2; break; | ||||
|   } | ||||
|   spiInit(spiRate); | ||||
| /** | ||||
|  * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset. | ||||
|  */ | ||||
| static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) { | ||||
|   while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1 | ||||
|   while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ }     // wait until BSY=0 | ||||
| } | ||||
|  | ||||
| uint8_t SPIClass::transfer(const uint8_t B) { return spiTransfer(B); } | ||||
| SPIClass::SPIClass(uint8_t device) { | ||||
|   // Init things specific to each SPI device | ||||
|   // clock divider setup is a bit of hack, and needs to be improved at a later date. | ||||
|  | ||||
|   PINSEL_CFG_Type PinCfg;  // data structure to hold init values | ||||
|   #if BOARD_NR_SPI >= 1 | ||||
|     _settings[0].spi_d = LPC_SSP0; | ||||
|     // _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); | ||||
|     PinCfg.Funcnum = 2; | ||||
|     PinCfg.OpenDrain = 0; | ||||
|     PinCfg.Pinmode = 0; | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_SCK_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_SCK_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_OUTPUT(BOARD_SPI1_SCK_PIN); | ||||
|  | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MISO_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MISO_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_INPUT(BOARD_SPI1_MISO_PIN); | ||||
|  | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MOSI_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MOSI_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_OUTPUT(BOARD_SPI1_MOSI_PIN); | ||||
|   #endif | ||||
|  | ||||
|   #if BOARD_NR_SPI >= 2 | ||||
|     _settings[1].spi_d = LPC_SSP1; | ||||
|     // _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); | ||||
|     PinCfg.Funcnum = 2; | ||||
|     PinCfg.OpenDrain = 0; | ||||
|     PinCfg.Pinmode = 0; | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_SCK_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_SCK_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_OUTPUT(BOARD_SPI2_SCK_PIN); | ||||
|  | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MISO_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MISO_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_INPUT(BOARD_SPI2_MISO_PIN); | ||||
|  | ||||
|     PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MOSI_PIN); | ||||
|     PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MOSI_PIN); | ||||
|     PINSEL_ConfigPin(&PinCfg); | ||||
|     SET_OUTPUT(BOARD_SPI2_MOSI_PIN); | ||||
|   #endif | ||||
|  | ||||
|   setModule(device); | ||||
|  | ||||
|   /* Initialize GPDMA controller */ | ||||
|   //TODO: call once in the constructor? or each time? | ||||
|   GPDMA_Init(); | ||||
| } | ||||
|  | ||||
| void SPIClass::begin() { | ||||
|   updateSettings(); | ||||
|   SSP_Cmd(_currentSetting->spi_d, ENABLE);  // start SSP running | ||||
| } | ||||
|  | ||||
| void SPIClass::beginTransaction(const SPISettings &cfg) { | ||||
|   setBitOrder(cfg.bitOrder); | ||||
|   setDataMode(cfg.dataMode); | ||||
|   setDataSize(cfg.dataSize); | ||||
|   //setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); | ||||
|   begin(); | ||||
| } | ||||
|  | ||||
| uint8_t SPIClass::transfer(const uint16_t b) { | ||||
|   /* send and receive a single byte */ | ||||
|   SSP_ReceiveData(_currentSetting->spi_d); // read any previous data | ||||
|   SSP_SendData(_currentSetting->spi_d, b); | ||||
|   waitSpiTxEnd(_currentSetting->spi_d);  // wait for it to finish | ||||
|   return SSP_ReceiveData(_currentSetting->spi_d); | ||||
| } | ||||
|  | ||||
| uint16_t SPIClass::transfer16(const uint16_t data) { | ||||
|   return (transfer((data >> 8) & 0xFF) << 8) | ||||
|        | (transfer(data & 0xFF) & 0xFF); | ||||
| } | ||||
|  | ||||
| SPIClass SPI; | ||||
| void SPIClass::end() { | ||||
|   // SSP_Cmd(_currentSetting->spi_d, DISABLE);  // stop device or SSP_DeInit? | ||||
|   SSP_DeInit(_currentSetting->spi_d); | ||||
| } | ||||
|  | ||||
| void SPIClass::send(uint8_t data) { | ||||
|   SSP_SendData(_currentSetting->spi_d, data); | ||||
| } | ||||
|  | ||||
| void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) { | ||||
|   //TODO: LPC dma can only write 0xFFF bytes at once. | ||||
|   GPDMA_Channel_CFG_Type GPDMACfg; | ||||
|  | ||||
|   /* Configure GPDMA channel 0 -------------------------------------------------------------*/ | ||||
|   /* DMA Channel 0 */ | ||||
|   GPDMACfg.ChannelNum = 0; | ||||
|   // Source memory | ||||
|   GPDMACfg.SrcMemAddr = (uint32_t)buf; | ||||
|   // Destination memory - Not used | ||||
|   GPDMACfg.DstMemAddr = 0; | ||||
|   // Transfer size | ||||
|   GPDMACfg.TransferSize = (minc ? length : 1); | ||||
|   // Transfer width | ||||
|   GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE; | ||||
|   // Transfer type | ||||
|   GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P; | ||||
|   // Source connection - unused | ||||
|   GPDMACfg.SrcConn = 0; | ||||
|   // Destination connection | ||||
|   GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx; | ||||
|  | ||||
|   GPDMACfg.DMALLI = 0; | ||||
|  | ||||
|   // Enable dma on SPI | ||||
|   SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE); | ||||
|  | ||||
|   // if minc=false, I'm repeating the same byte 'length' times, as I could not find yet how do GPDMA without memory increment | ||||
|   do { | ||||
|     // Setup channel with given parameter | ||||
|     GPDMA_Setup(&GPDMACfg); | ||||
|  | ||||
|     // enabled dma | ||||
|     GPDMA_ChannelCmd(0, ENABLE); | ||||
|  | ||||
|     // wait data transfer | ||||
|     while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) { } | ||||
|  | ||||
|     // clear err and int | ||||
|     GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0); | ||||
|     GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0); | ||||
|  | ||||
|     // dma disable | ||||
|     GPDMA_ChannelCmd(0, DISABLE); | ||||
|  | ||||
|     --length; | ||||
|   } while (!minc && length > 0); | ||||
|  | ||||
|   waitSpiTxEnd(_currentSetting->spi_d); | ||||
|  | ||||
|   SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE); | ||||
| } | ||||
|  | ||||
| uint16_t SPIClass::read() { | ||||
|   return SSP_ReceiveData(_currentSetting->spi_d); | ||||
| } | ||||
|  | ||||
| void SPIClass::read(uint8_t *buf, uint32_t len) { | ||||
|   for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF); | ||||
| } | ||||
|  | ||||
| void SPIClass::setClock(uint32_t clock) { | ||||
|   _currentSetting->clock = clock; | ||||
| } | ||||
|  | ||||
| void SPIClass::setModule(uint8_t device) { | ||||
|   _currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed | ||||
| } | ||||
|  | ||||
| void SPIClass::setBitOrder(uint8_t bitOrder) { | ||||
|   _currentSetting->bitOrder = bitOrder; | ||||
| } | ||||
|  | ||||
| void SPIClass::setDataMode(uint8_t dataMode) { | ||||
|   _currentSetting->dataSize = dataMode; | ||||
| } | ||||
|  | ||||
| void SPIClass::setDataSize(uint32_t ds) { | ||||
|   _currentSetting->dataSize = ds; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set up/tear down | ||||
|  */ | ||||
| void SPIClass::updateSettings() { | ||||
|   //SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?! | ||||
|  | ||||
|   // divide PCLK by 2 for SSP0 | ||||
|   CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2); | ||||
|  | ||||
|   SSP_CFG_Type HW_SPI_init; // data structure to hold init values | ||||
|   SSP_ConfigStructInit(&HW_SPI_init);  // set values for SPI mode | ||||
|   HW_SPI_init.ClockRate = _currentSetting->clock; | ||||
|   HW_SPI_init.Databit = _currentSetting->dataSize; | ||||
|  | ||||
|   /** | ||||
|    * SPI Mode  CPOL  CPHA  Shift SCK-edge  Capture SCK-edge | ||||
|    * 0       0     0     Falling     Rising | ||||
|    * 1       0     1     Rising      Falling | ||||
|    * 2       1     0     Rising      Falling | ||||
|    * 3       1     1     Falling     Rising | ||||
|    */ | ||||
|   switch (_currentSetting->dataMode) { | ||||
|     case SPI_MODE0: | ||||
|       HW_SPI_init.CPHA = SSP_CPHA_FIRST; | ||||
| 	    HW_SPI_init.CPOL = SSP_CPOL_HI; | ||||
|       break; | ||||
|     case SPI_MODE1: | ||||
|       HW_SPI_init.CPHA = SSP_CPHA_SECOND; | ||||
| 	    HW_SPI_init.CPOL = SSP_CPOL_HI; | ||||
|       break; | ||||
|     case SPI_MODE2: | ||||
|       HW_SPI_init.CPHA = SSP_CPHA_FIRST; | ||||
| 	    HW_SPI_init.CPOL = SSP_CPOL_LO; | ||||
|       break; | ||||
|     case SPI_MODE3: | ||||
|       HW_SPI_init.CPHA = SSP_CPHA_SECOND; | ||||
| 	    HW_SPI_init.CPOL = SSP_CPOL_LO; | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   // TODO: handle bitOrder | ||||
|   SSP_Init(_currentSetting->spi_d, &HW_SPI_init);  // puts the values into the proper bits in the SSP0 registers | ||||
| } | ||||
|  | ||||
| #if MISO_PIN == BOARD_SPI1_MISO_PIN | ||||
|   SPIClass SPI(1); | ||||
| #elif MISO_PIN == BOARD_SPI2_MISO_PIN | ||||
|   SPIClass SPI(2); | ||||
| #endif | ||||
|  | ||||
| #endif // TARGET_LPC1768 | ||||
|   | ||||
| @@ -21,6 +21,13 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #if HAS_SPI_TFT || HAS_FSMC_TFT | ||||
|   #error "Sorry! TFT displays are not available for HAL/LPC1768." | ||||
| #if HAS_FSMC_TFT | ||||
|   #error "Sorry! FSMC TFT displays are not current available for HAL/LPC1768." | ||||
| #endif | ||||
|  | ||||
| // This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046' | ||||
| #if ENABLED(TOUCH_SCREEN) && !HAS_GRAPHICAL_TFT | ||||
|   #undef TOUCH_SCREEN | ||||
|   #undef TOUCH_SCREEN_CALIBRATION | ||||
|   #define HAS_TOUCH_XPT2046 1 | ||||
| #endif | ||||
|   | ||||
| @@ -24,25 +24,139 @@ | ||||
| #include "../../shared/HAL_SPI.h" | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <lpc17xx_ssp.h> | ||||
| #include <lpc17xx_gpdma.h> | ||||
|  | ||||
| #define MSBFIRST 1 | ||||
| #define SPI_MODE3 0 | ||||
| //#define MSBFIRST 1 | ||||
|  | ||||
| #define SPI_MODE0 0 | ||||
| #define SPI_MODE1 1 | ||||
| #define SPI_MODE2 2 | ||||
| #define SPI_MODE3 3 | ||||
|  | ||||
| #define DATA_SIZE_8BIT SSP_DATABIT_8 | ||||
| #define DATA_SIZE_16BIT SSP_DATABIT_16 | ||||
|  | ||||
| #define SPI_CLOCK_DIV2   8333333 //(SCR:  2)  desired: 8,000,000  actual: 8,333,333  +4.2%  SPI_FULL_SPEED | ||||
| #define SPI_CLOCK_DIV4   4166667 //(SCR:  5)  desired: 4,000,000  actual: 4,166,667  +4.2%  SPI_HALF_SPEED | ||||
| #define SPI_CLOCK_DIV8   2083333 //(SCR: 11)  desired: 2,000,000  actual: 2,083,333  +4.2%  SPI_QUARTER_SPEED | ||||
| #define SPI_CLOCK_DIV16  1000000 //(SCR: 24)  desired: 1,000,000  actual: 1,000,000         SPI_EIGHTH_SPEED | ||||
| #define SPI_CLOCK_DIV32   500000 //(SCR: 49)  desired:   500,000  actual:   500,000         SPI_SPEED_5 | ||||
| #define SPI_CLOCK_DIV64   250000 //(SCR: 99)  desired:   250,000  actual:   250,000         SPI_SPEED_6 | ||||
| #define SPI_CLOCK_DIV128  125000 //(SCR:199)  desired:   125,000  actual:   125,000         Default from HAL.h | ||||
|  | ||||
| #define SPI_CLOCK_MAX SPI_CLOCK_DIV2 | ||||
|  | ||||
| #define BOARD_NR_SPI 2 | ||||
|  | ||||
| //#define BOARD_SPI1_NSS_PIN      PA4 ?! | ||||
| #define BOARD_SPI1_SCK_PIN      P0_15 | ||||
| #define BOARD_SPI1_MISO_PIN     P0_17 | ||||
| #define BOARD_SPI1_MOSI_PIN     P0_18 | ||||
|  | ||||
| //#define BOARD_SPI2_NSS_PIN      PB12 ?! | ||||
| #define BOARD_SPI2_SCK_PIN      P0_07 | ||||
| #define BOARD_SPI2_MISO_PIN     P0_08 | ||||
| #define BOARD_SPI2_MOSI_PIN     P0_09 | ||||
|  | ||||
| class SPISettings { | ||||
|   public: | ||||
| public: | ||||
|   SPISettings(uint32_t speed, int, int) : spi_speed(speed) {}; | ||||
|   SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) { | ||||
|     if (__builtin_constant_p(inClock)) | ||||
|       init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize); | ||||
|     else | ||||
|       init_MightInline(inClock, inBitOrder, inDataMode, inDataSize); | ||||
|   } | ||||
|   SPISettings() { | ||||
|     init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); | ||||
|   } | ||||
|  | ||||
|   uint32_t spiRate() const { return spi_speed; } | ||||
|   private: | ||||
|  | ||||
| private: | ||||
|   void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) { | ||||
|     init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize); | ||||
|   } | ||||
|   void init_AlwaysInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) { | ||||
|     clock    = inClock; | ||||
|     bitOrder = inBitOrder; | ||||
|     dataMode = inDataMode; | ||||
|     dataSize = inDataSize; | ||||
|   } | ||||
|  | ||||
|   uint32_t spi_speed; | ||||
|   uint32_t clock; | ||||
|   uint32_t dataSize; | ||||
|   //uint32_t clockDivider; | ||||
|   uint8_t bitOrder; | ||||
|   uint8_t dataMode; | ||||
|   LPC_SSP_TypeDef *spi_d; | ||||
|  | ||||
|   friend class SPIClass; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * @brief Wirish SPI interface. | ||||
|  * | ||||
|  * This is the same interface is available across HAL | ||||
|  * | ||||
|  * This implementation uses software slave management, so the caller | ||||
|  * is responsible for controlling the slave select line. | ||||
|  */ | ||||
| class SPIClass { | ||||
|   public: | ||||
| public: | ||||
|   /** | ||||
|    * @param spiPortNumber Number of the SPI port to manage. | ||||
|    */ | ||||
|   SPIClass(uint8_t spiPortNumber); | ||||
|  | ||||
|   /** | ||||
|    * Select and configure the current selected SPI device to use | ||||
|    */ | ||||
|   void begin(); | ||||
|  | ||||
|   /** | ||||
|    * Disable the current SPI device | ||||
|    */ | ||||
|   void end(); | ||||
|  | ||||
|   void beginTransaction(const SPISettings&); | ||||
|   void endTransaction() {}; | ||||
|     uint8_t transfer(uint8_t data); | ||||
|  | ||||
|   // Transfer using 1 "Data Size" | ||||
|   uint8_t transfer(uint16_t data); | ||||
|   // Transfer 2 bytes in 8 bit mode | ||||
|   uint16_t transfer16(uint16_t data); | ||||
|  | ||||
|   void send(uint8_t data); | ||||
|  | ||||
|   uint16_t read(); | ||||
|   void read(uint8_t *buf, uint32_t len); | ||||
|  | ||||
|   void dmaSend(void *buf, uint16_t length, bool minc); | ||||
|  | ||||
|   /** | ||||
|    * @brief Sets the number of the SPI peripheral to be used by | ||||
|    *        this HardwareSPI instance. | ||||
|    * | ||||
|    * @param spi_num Number of the SPI port. 1-2 in low density devices | ||||
|    *     or 1-3 in high density devices. | ||||
|    */ | ||||
|   void setModule(uint8_t device); | ||||
|  | ||||
|   void setClock(uint32_t clock); | ||||
|   void setBitOrder(uint8_t bitOrder); | ||||
|   void setDataMode(uint8_t dataMode); | ||||
|   void setDataSize(uint32_t ds); | ||||
|  | ||||
|   inline uint32_t getDataSize() { return _currentSetting->dataSize; } | ||||
|  | ||||
| private: | ||||
|   SPISettings _settings[BOARD_NR_SPI]; | ||||
|   SPISettings *_currentSetting; | ||||
|  | ||||
|   void updateSettings(); | ||||
| }; | ||||
|  | ||||
| extern SPIClass SPI; | ||||
|   | ||||
							
								
								
									
										153
									
								
								Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if HAS_SPI_TFT | ||||
|  | ||||
| #include "tft_spi.h" | ||||
|  | ||||
| //TFT_SPI tft; | ||||
|  | ||||
| SPIClass TFT_SPI::SPIx(1); | ||||
|  | ||||
| #define TFT_CS_H  WRITE(TFT_CS_PIN, HIGH) | ||||
| #define TFT_CS_L  WRITE(TFT_CS_PIN, LOW) | ||||
|  | ||||
| #define TFT_DC_H  WRITE(TFT_DC_PIN, HIGH) | ||||
| #define TFT_DC_L  WRITE(TFT_DC_PIN, LOW) | ||||
|  | ||||
| #define TFT_RST_H WRITE(TFT_RESET_PIN, HIGH) | ||||
| #define TFT_RST_L WRITE(TFT_RESET_PIN, LOW) | ||||
|  | ||||
| #define TFT_BLK_H WRITE(TFT_BACKLIGHT_PIN, HIGH) | ||||
| #define TFT_BLK_L WRITE(TFT_BACKLIGHT_PIN, LOW) | ||||
|  | ||||
| void TFT_SPI::Init() { | ||||
|   #if PIN_EXISTS(TFT_RESET) | ||||
|     SET_OUTPUT(TFT_RESET_PIN); | ||||
|     TFT_RST_H; | ||||
|     delay(100); | ||||
|   #endif | ||||
|  | ||||
|   #if PIN_EXISTS(TFT_BACKLIGHT) | ||||
|     SET_OUTPUT(TFT_BACKLIGHT_PIN); | ||||
|     TFT_BLK_H; | ||||
|   #endif | ||||
|  | ||||
|   SET_OUTPUT(TFT_DC_PIN); | ||||
|   SET_OUTPUT(TFT_CS_PIN); | ||||
|  | ||||
|   TFT_DC_H; | ||||
|   TFT_CS_H; | ||||
|  | ||||
|   /** | ||||
|    * STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz | ||||
|    * STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1 | ||||
|    * so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2 | ||||
|    */ | ||||
|   #if 0 | ||||
|     #if SPI_DEVICE == 1 | ||||
|      #define SPI_CLOCK_MAX SPI_CLOCK_DIV4 | ||||
|     #else | ||||
|      #define SPI_CLOCK_MAX SPI_CLOCK_DIV2 | ||||
|     #endif | ||||
|     uint8_t  clock; | ||||
|     uint8_t spiRate = SPI_FULL_SPEED; | ||||
|     switch (spiRate) { | ||||
|      case SPI_FULL_SPEED:    clock = SPI_CLOCK_MAX ;  break; | ||||
|      case SPI_HALF_SPEED:    clock = SPI_CLOCK_DIV4 ; break; | ||||
|      case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break; | ||||
|      case SPI_EIGHTH_SPEED:  clock = SPI_CLOCK_DIV16; break; | ||||
|      case SPI_SPEED_5:       clock = SPI_CLOCK_DIV32; break; | ||||
|      case SPI_SPEED_6:       clock = SPI_CLOCK_DIV64; break; | ||||
|      default:                clock = SPI_CLOCK_DIV2;  // Default from the SPI library | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   #if TFT_MISO_PIN == BOARD_SPI1_MISO_PIN | ||||
|     SPIx.setModule(1); | ||||
|   #elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN | ||||
|     SPIx.setModule(2); | ||||
|   #endif | ||||
|   SPIx.setClock(SPI_CLOCK_MAX); | ||||
|   SPIx.setBitOrder(MSBFIRST); | ||||
|   SPIx.setDataMode(SPI_MODE0); | ||||
| } | ||||
|  | ||||
| void TFT_SPI::DataTransferBegin(uint16_t DataSize) { | ||||
|   SPIx.setDataSize(DataSize); | ||||
|   SPIx.begin(); | ||||
|   TFT_CS_L; | ||||
| } | ||||
|  | ||||
| uint32_t TFT_SPI::GetID() { | ||||
|   uint32_t id; | ||||
|   id = ReadID(LCD_READ_ID); | ||||
|   if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF) | ||||
|     id = ReadID(LCD_READ_ID4); | ||||
|   return id; | ||||
| } | ||||
|  | ||||
| uint32_t TFT_SPI::ReadID(uint16_t Reg) { | ||||
|   uint32_t data = 0; | ||||
|  | ||||
|   #if PIN_EXISTS(TFT_MISO) | ||||
|     uint8_t d = 0; | ||||
|     SPIx.setDataSize(DATASIZE_8BIT); | ||||
|     SPIx.setClock(SPI_CLOCK_DIV64); | ||||
|     SPIx.begin(); | ||||
|     TFT_CS_L; | ||||
|     WriteReg(Reg); | ||||
|  | ||||
|     LOOP_L_N(i, 4) { | ||||
|       SPIx.read((uint8_t*)&d, 1); | ||||
|       data = (data << 8) | d; | ||||
|     } | ||||
|  | ||||
|     DataTransferEnd(); | ||||
|     SPIx.setClock(SPI_CLOCK_MAX); | ||||
|   #endif | ||||
|  | ||||
|   return data >> 7; | ||||
| } | ||||
|  | ||||
| bool TFT_SPI::isBusy() { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| void TFT_SPI::Abort() { | ||||
|   DataTransferEnd(); | ||||
| } | ||||
|  | ||||
| void TFT_SPI::Transmit(uint16_t Data) { | ||||
|   SPIx.transfer(Data); | ||||
| } | ||||
|  | ||||
| void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { | ||||
|   DataTransferBegin(DATASIZE_16BIT); //16 | ||||
|   TFT_DC_H; | ||||
|   SPIx.dmaSend(Data, Count, MemoryIncrease); | ||||
|   DataTransferEnd(); | ||||
| } | ||||
|  | ||||
| #endif // HAS_SPI_TFT | ||||
							
								
								
									
										77
									
								
								Marlin/src/HAL/LPC1768/tft/tft_spi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								Marlin/src/HAL/LPC1768/tft/tft_spi.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #include <SPI.h> | ||||
| #include <lpc17xx_ssp.h> | ||||
| // #include <lpc17xx_gpdma.h> | ||||
|  | ||||
| #ifndef LCD_READ_ID | ||||
|   #define LCD_READ_ID  0x04   // Read display identification information (0xD3 on ILI9341) | ||||
| #endif | ||||
| #ifndef LCD_READ_ID4 | ||||
|   #define LCD_READ_ID4 0xD3   // Read display identification information (0xD3 on ILI9341) | ||||
| #endif | ||||
|  | ||||
| #define DATASIZE_8BIT    SSP_DATABIT_8 | ||||
| #define DATASIZE_16BIT   SSP_DATABIT_16 | ||||
| #define TFT_IO TFT_SPI | ||||
|  | ||||
| #define DMA_MINC_ENABLE 1 | ||||
| #define DMA_MINC_DISABLE 0 | ||||
|  | ||||
| class TFT_SPI { | ||||
| private: | ||||
|   static uint32_t ReadID(uint16_t Reg); | ||||
|   static void Transmit(uint16_t Data); | ||||
|   static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); | ||||
|  | ||||
| public: | ||||
|   static SPIClass SPIx; | ||||
|  | ||||
|   static void Init(); | ||||
|   static uint32_t GetID(); | ||||
|   static bool isBusy(); | ||||
|   static void Abort(); | ||||
|  | ||||
|   static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT); | ||||
|   static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); }; | ||||
|   static void DataTransferAbort(); | ||||
|  | ||||
|   static void WriteData(uint16_t Data) { Transmit(Data); } | ||||
|   static void WriteReg(uint16_t Reg) { OUT_WRITE(TFT_A0_PIN, LOW); Transmit(Reg); OUT_WRITE(TFT_A0_PIN, HIGH); } | ||||
|  | ||||
|   static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); } | ||||
|   // static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); } | ||||
|   static void WriteMultiple(uint16_t Color, uint32_t Count) { | ||||
|     static uint16_t Data; Data = Color; | ||||
|     //LPC dma can only write 0xFFF bytes at once. | ||||
|     #define MAX_DMA_SIZE (0xFFF - 1) | ||||
|     while (Count > 0) { | ||||
|       TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count); | ||||
|       Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0; | ||||
|     } | ||||
|     #undef MAX_DMA_SIZE | ||||
|   } | ||||
| }; | ||||
							
								
								
									
										129
									
								
								Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046 | ||||
|  | ||||
| #include "xpt2046.h" | ||||
| #include <SPI.h> | ||||
|  | ||||
| uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; } | ||||
|  | ||||
| #if ENABLED(TOUCH_BUTTONS_HW_SPI) | ||||
|   #include <SPI.h> | ||||
|  | ||||
|   SPIClass XPT2046::SPIx(TOUCH_BUTTONS_HW_SPI_DEVICE); | ||||
|  | ||||
|   static void touch_spi_init(uint8_t spiRate) { | ||||
|     XPT2046::SPIx.setModule(TOUCH_BUTTONS_HW_SPI_DEVICE); | ||||
|     XPT2046::SPIx.setClock(SPI_CLOCK_DIV128); | ||||
|     XPT2046::SPIx.setBitOrder(MSBFIRST); | ||||
|     XPT2046::SPIx.setDataMode(SPI_MODE0); | ||||
|     XPT2046::SPIx.setDataSize(DATA_SIZE_8BIT); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| void XPT2046::Init() { | ||||
|   SET_INPUT(TOUCH_MISO_PIN); | ||||
|   SET_OUTPUT(TOUCH_MOSI_PIN); | ||||
|   SET_OUTPUT(TOUCH_SCK_PIN); | ||||
|   OUT_WRITE(TOUCH_CS_PIN, HIGH); | ||||
|  | ||||
|   #if PIN_EXISTS(TOUCH_INT) | ||||
|     // Optional Pendrive interrupt pin | ||||
|     SET_INPUT(TOUCH_INT_PIN); | ||||
|   #endif | ||||
|  | ||||
|   TERN_(TOUCH_BUTTONS_HW_SPI, touch_spi_init(SPI_SPEED_6)); | ||||
|  | ||||
|   // Read once to enable pendrive status pin | ||||
|   getRawData(XPT2046_X); | ||||
| } | ||||
|  | ||||
| bool XPT2046::isTouched() { | ||||
|   return isBusy() ? false : ( | ||||
|     #if PIN_EXISTS(TOUCH_INT) | ||||
|       READ(TOUCH_INT_PIN) != HIGH | ||||
|     #else | ||||
|       getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD | ||||
|     #endif | ||||
|   ); | ||||
| } | ||||
|  | ||||
| bool XPT2046::getRawPoint(int16_t *x, int16_t *y) { | ||||
|   if (isBusy()) return false; | ||||
|   if (!isTouched()) return false; | ||||
|   *x = getRawData(XPT2046_X); | ||||
|   *y = getRawData(XPT2046_Y); | ||||
|   SERIAL_ECHOLNPAIR("X: ", *x, ", Y: ", *y); | ||||
|   return isTouched(); | ||||
| } | ||||
|  | ||||
| uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) { | ||||
|   uint16_t data[3]; | ||||
|  | ||||
|   DataTransferBegin(); | ||||
|   TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.begin()); | ||||
|  | ||||
|   for (uint16_t i = 0; i < 3 ; i++) { | ||||
|     IO(coordinate); | ||||
|     data[i] = (IO() << 4) | (IO() >> 4); | ||||
|   } | ||||
|  | ||||
|   TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.end()); | ||||
|   DataTransferEnd(); | ||||
|  | ||||
|   uint16_t delta01 = delta(data[0], data[1]), | ||||
|            delta02 = delta(data[0], data[2]), | ||||
|            delta12 = delta(data[1], data[2]); | ||||
|  | ||||
|   if (delta01 > delta02 || delta01 > delta12) | ||||
|     data[delta02 > delta12 ? 0 : 1] = data[2]; | ||||
|  | ||||
|   return (data[0] + data[1]) >> 1; | ||||
| } | ||||
|  | ||||
| uint16_t XPT2046::IO(uint16_t data) { | ||||
|   return TERN(TOUCH_BUTTONS_HW_SPI, HardwareIO, SoftwareIO)(data); | ||||
| } | ||||
|  | ||||
| extern uint8_t spiTransfer(uint8_t b); | ||||
|  | ||||
| #if ENABLED(TOUCH_BUTTONS_HW_SPI) | ||||
|   uint16_t XPT2046::HardwareIO(uint16_t data) { | ||||
|     return SPIx.transfer(data & 0xFF); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| uint16_t XPT2046::SoftwareIO(uint16_t data) { | ||||
|   uint16_t result = 0; | ||||
|  | ||||
|   for (uint8_t j = 0x80; j; j >>= 1) { | ||||
|     WRITE(TOUCH_SCK_PIN, LOW); | ||||
|     WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW); | ||||
|     if (READ(TOUCH_MISO_PIN)) result |= j; | ||||
|     WRITE(TOUCH_SCK_PIN, HIGH); | ||||
|   } | ||||
|   WRITE(TOUCH_SCK_PIN, LOW); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| #endif // HAS_TFT_XPT2046 | ||||
							
								
								
									
										80
									
								
								Marlin/src/HAL/LPC1768/tft/xpt2046.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Marlin/src/HAL/LPC1768/tft/xpt2046.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if ENABLED(TOUCH_BUTTONS_HW_SPI) | ||||
|   #include <SPI.h> | ||||
| #endif | ||||
|  | ||||
| #ifndef TOUCH_MISO_PIN | ||||
|   #define TOUCH_MISO_PIN MISO_PIN | ||||
| #endif | ||||
| #ifndef TOUCH_MOSI_PIN | ||||
|   #define TOUCH_MOSI_PIN MOSI_PIN | ||||
| #endif | ||||
| #ifndef TOUCH_SCK_PIN | ||||
|   #define TOUCH_SCK_PIN  SCK_PIN | ||||
| #endif | ||||
| #ifndef TOUCH_CS_PIN | ||||
|   #define TOUCH_CS_PIN   CS_PIN | ||||
| #endif | ||||
| #ifndef TOUCH_INT_PIN | ||||
|   #define TOUCH_INT_PIN  -1 | ||||
| #endif | ||||
|  | ||||
| #define XPT2046_DFR_MODE        0x00 | ||||
| #define XPT2046_SER_MODE        0x04 | ||||
| #define XPT2046_CONTROL         0x80 | ||||
|  | ||||
| enum XPTCoordinate : uint8_t { | ||||
|   XPT2046_X  = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE, | ||||
|   XPT2046_Y  = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE, | ||||
|   XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE, | ||||
|   XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE, | ||||
| }; | ||||
|  | ||||
| #if !defined(XPT2046_Z1_THRESHOLD) | ||||
|   #define XPT2046_Z1_THRESHOLD 10 | ||||
| #endif | ||||
|  | ||||
| class XPT2046 { | ||||
| private: | ||||
|   static bool isBusy() { return false; } | ||||
|  | ||||
|   static uint16_t getRawData(const XPTCoordinate coordinate); | ||||
|   static bool isTouched(); | ||||
|  | ||||
|   static inline void DataTransferBegin() { WRITE(TOUCH_CS_PIN, LOW); }; | ||||
|   static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); }; | ||||
|   #if ENABLED(TOUCH_BUTTONS_HW_SPI) | ||||
|     static uint16_t HardwareIO(uint16_t data); | ||||
|   #endif | ||||
|   static uint16_t SoftwareIO(uint16_t data); | ||||
|   static uint16_t IO(uint16_t data = 0); | ||||
|  | ||||
| public: | ||||
|   #if ENABLED(TOUCH_BUTTONS_HW_SPI) | ||||
|     static SPIClass SPIx; | ||||
|   #endif | ||||
|  | ||||
|   static void Init(); | ||||
|   static bool getRawPoint(int16_t *x, int16_t *y); | ||||
| }; | ||||
| @@ -82,11 +82,6 @@ | ||||
|  | ||||
|   #define U8G_COM_SSD_I2C_HAL         u8g_com_arduino_ssd_i2c_fn | ||||
|  | ||||
|   #if EITHER(FSMC_GRAPHICAL_TFT, SPI_GRAPHICAL_TFT) | ||||
|     uint8_t u8g_com_stm32duino_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_HAL_TFT_FN       u8g_com_stm32duino_tft_fn | ||||
|   #endif | ||||
|  | ||||
| #elif defined(TARGET_LPC1768) | ||||
|  | ||||
|   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 @@ | ||||
| #ifndef U8G_COM_SSD_I2C_HAL | ||||
|   #define U8G_COM_SSD_I2C_HAL       u8g_com_null_fn | ||||
| #endif | ||||
| #ifndef U8G_COM_HAL_TFT_FN | ||||
| #if EITHER(FSMC_GRAPHICAL_TFT, SPI_GRAPHICAL_TFT) | ||||
|   uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|   #define U8G_COM_HAL_TFT_FN       u8g_com_hal_tft_fn | ||||
| #else | ||||
|   #define U8G_COM_HAL_TFT_FN       u8g_com_null_fn | ||||
| #endif | ||||
|   | ||||
| @@ -760,7 +760,7 @@ uint8_t u8g_dev_tft_320x240_upscale_from_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, u | ||||
|  | ||||
| static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT | ||||
|  | ||||
| uint8_t u8g_com_stm32duino_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { | ||||
| uint8_t u8g_com_hal_tft_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { | ||||
|   if (msgInitCount) { | ||||
|     if (msg == U8G_COM_MSG_INIT) msgInitCount--; | ||||
|     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 | ||||
|       break; | ||||
|  | ||||
|     case U8G_COM_MSG_WRITE_SEQ: | ||||
|       tftio.DataTransferBegin(DATASIZE_8BIT); | ||||
|       tftio.DataTransferBegin(DATASIZE_16BIT); | ||||
|       for (uint8_t i = 0; i < arg_val; i += 2) | ||||
|         tftio.WriteData(*(uint16_t *)(((uint32_t)arg_ptr) + i)); | ||||
|       tftio.DataTransferEnd(); | ||||
|   | ||||
| @@ -274,6 +274,38 @@ | ||||
|     #define FORCE_SOFT_SPI | ||||
|     #define LCD_BACKLIGHT_PIN              -1 | ||||
|  | ||||
|   #elif HAS_SPI_TFT                               // Config for Classic UI (emulated DOGM) and Color UI | ||||
|     #define SS_PIN                         -1 | ||||
|     //#define ONBOARD_SD_CS_PIN            -1 | ||||
|  | ||||
|     #define TFT_CS_PIN                     P1_22 | ||||
|     #define TFT_A0_PIN                     P1_23 | ||||
|     #define TFT_DC_PIN                     P1_23 | ||||
|     #define TFT_MISO_PIN                   P0_17 | ||||
|     #define TFT_BACKLIGHT_PIN              P1_18 | ||||
|     #define TFT_RESET_PIN                  P1_19 | ||||
|  | ||||
|     #define LPC_HW_SPI_DEV                     0 | ||||
|     #define LCD_USE_DMA_SPI | ||||
|  | ||||
|     #define TOUCH_INT_PIN                  P1_21 | ||||
|     #define TOUCH_CS_PIN                   P1_20 | ||||
|     #define TOUCH_BUTTONS_HW_SPI | ||||
|     #define TOUCH_BUTTONS_HW_SPI_DEVICE        1 | ||||
|  | ||||
|     #ifndef GRAPHICAL_TFT_UPSCALE | ||||
|       #define GRAPHICAL_TFT_UPSCALE            3 | ||||
|     #endif | ||||
|  | ||||
|     // SPI 1 | ||||
|     #define SCK_PIN                        P0_15 | ||||
|     #define MISO_PIN                       P0_17 | ||||
|     #define MOSI_PIN                       P0_18 | ||||
|  | ||||
|     // Disable any LCD related PINs config | ||||
|     #define LCD_PINS_ENABLE                -1 | ||||
|     #define LCD_PINS_RS                    -1 | ||||
|  | ||||
|   #else | ||||
|  | ||||
|     #define BTN_ENC                        P0_28  // (58) open-drain | ||||
|   | ||||
| @@ -1421,3 +1421,22 @@ | ||||
| #if PIN_EXISTS(ESP_WIFI_MODULE_GPIO2) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, ESP_WIFI_MODULE_GPIO2_PIN) | ||||
| #endif | ||||
| // TFT PINS | ||||
| #if PIN_EXISTS(TFT_CS) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_CS_PIN) | ||||
| #endif | ||||
| #if PIN_EXISTS(TFT_A0) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_A0_PIN) | ||||
| #endif | ||||
| #if PIN_EXISTS(TFT_DC) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_DC_PIN) | ||||
| #endif | ||||
| #if PIN_EXISTS(TFT_MISO) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_MISO_PIN) | ||||
| #endif | ||||
| #if PIN_EXISTS(TFT_BACKLIGHT) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_BACKLIGHT_PIN) | ||||
| #endif | ||||
| #if PIN_EXISTS(TFT_RESET) | ||||
|   REPORT_NAME_DIGITAL(__LINE__, TFT_RESET_PIN) | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user