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 |  * The hardware SPI runs faster and has higher throughput but is not compatible | ||||||
|  * with some LCD interfaces/adapters. |  * with some LCD interfaces/adapters. | ||||||
|  * |  * | ||||||
| @@ -51,6 +51,10 @@ | |||||||
| #include "../../inc/MarlinConfig.h" | #include "../../inc/MarlinConfig.h" | ||||||
| #include <SPI.h> | #include <SPI.h> | ||||||
|  |  | ||||||
|  | // Hardware SPI and SPIClass | ||||||
|  | #include <lpc17xx_pinsel.h> | ||||||
|  | #include <lpc17xx_clkpwr.h> | ||||||
|  |  | ||||||
| // ------------------------ | // ------------------------ | ||||||
| // Public functions | // Public functions | ||||||
| // ------------------------ | // ------------------------ | ||||||
| @@ -96,12 +100,6 @@ | |||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
|   // Hardware SPI |  | ||||||
|  |  | ||||||
|   #include <lpc17xx_pinsel.h> |  | ||||||
|   #include <lpc17xx_ssp.h> |  | ||||||
|   #include <lpc17xx_clkpwr.h> |  | ||||||
|  |  | ||||||
|   // decide which HW SPI device to use |   // decide which HW SPI device to use | ||||||
|   #ifndef LPC_HW_SPI_DEV |   #ifndef LPC_HW_SPI_DEV | ||||||
|     #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09) |     #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09) | ||||||
| @@ -114,7 +112,7 @@ | |||||||
|       #endif |       #endif | ||||||
|     #endif |     #endif | ||||||
|   #endif |   #endif | ||||||
|   #if (LPC_HW_SPI_DEV == 0) |   #if LPC_HW_SPI_DEV == 0 | ||||||
|     #define LPC_SSPn LPC_SSP0 |     #define LPC_SSPn LPC_SSP0 | ||||||
|   #else |   #else | ||||||
|     #define LPC_SSPn LPC_SSP1 |     #define LPC_SSPn LPC_SSP1 | ||||||
| @@ -192,7 +190,7 @@ | |||||||
|     for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF); |     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); |     return doio(b); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -211,30 +209,236 @@ | |||||||
|  |  | ||||||
| #endif // LPC_SOFTWARE_SPI | #endif // LPC_SOFTWARE_SPI | ||||||
|  |  | ||||||
| void SPIClass::begin() { spiBegin(); } | /** | ||||||
|  |  * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset. | ||||||
| void SPIClass::beginTransaction(const SPISettings &cfg) { |  */ | ||||||
|   uint8_t spiRate; | static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) { | ||||||
|   switch (cfg.spiRate()) { |   while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1 | ||||||
|     case 8000000: spiRate = 0; break; |   while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ }     // wait until BSY=0 | ||||||
|     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); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 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) { | uint16_t SPIClass::transfer16(const uint16_t data) { | ||||||
|   return (transfer((data >> 8) & 0xFF) << 8) |   return (transfer((data >> 8) & 0xFF) << 8) | ||||||
|        | (transfer(data & 0xFF) & 0xFF); |        | (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 | #endif // TARGET_LPC1768 | ||||||
|   | |||||||
| @@ -21,6 +21,13 @@ | |||||||
|  */ |  */ | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #if HAS_SPI_TFT || HAS_FSMC_TFT | #if HAS_FSMC_TFT | ||||||
|   #error "Sorry! TFT displays are not available for HAL/LPC1768." |   #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 | #endif | ||||||
|   | |||||||
| @@ -24,25 +24,139 @@ | |||||||
| #include "../../shared/HAL_SPI.h" | #include "../../shared/HAL_SPI.h" | ||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <lpc17xx_ssp.h> | ||||||
|  | #include <lpc17xx_gpdma.h> | ||||||
|  |  | ||||||
| #define MSBFIRST 1 | //#define MSBFIRST 1 | ||||||
| #define SPI_MODE3 0 |  | ||||||
|  | #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 { | class SPISettings { | ||||||
|   public: | public: | ||||||
|     SPISettings(uint32_t speed, int, int) : spi_speed(speed) {}; |   SPISettings(uint32_t speed, int, int) : spi_speed(speed) {}; | ||||||
|     uint32_t spiRate() const { return spi_speed; } |   SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) { | ||||||
|   private: |     if (__builtin_constant_p(inClock)) | ||||||
|     uint32_t spi_speed; |       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: | ||||||
|  |   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 { | class SPIClass { | ||||||
|   public: | public: | ||||||
|     void begin(); |   /** | ||||||
|     void beginTransaction(const SPISettings&); |    * @param spiPortNumber Number of the SPI port to manage. | ||||||
|     void endTransaction() {}; |    */ | ||||||
|     uint8_t transfer(uint8_t data); |   SPIClass(uint8_t spiPortNumber); | ||||||
|     uint16_t transfer16(uint16_t data); |  | ||||||
|  |   /** | ||||||
|  |    * 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() {}; | ||||||
|  |  | ||||||
|  |   // 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; | 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 |   #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) | #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); |   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 | #ifndef U8G_COM_SSD_I2C_HAL | ||||||
|   #define U8G_COM_SSD_I2C_HAL       u8g_com_null_fn |   #define U8G_COM_SSD_I2C_HAL       u8g_com_null_fn | ||||||
| #endif | #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 |   #define U8G_COM_HAL_TFT_FN       u8g_com_null_fn | ||||||
| #endif | #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 | 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 (msgInitCount) { | ||||||
|     if (msg == U8G_COM_MSG_INIT) msgInitCount--; |     if (msg == U8G_COM_MSG_INIT) msgInitCount--; | ||||||
|     if (msgInitCount) return -1; |     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; |       break; | ||||||
|  |  | ||||||
|     case U8G_COM_MSG_WRITE_SEQ: |     case U8G_COM_MSG_WRITE_SEQ: | ||||||
|       tftio.DataTransferBegin(DATASIZE_8BIT); |       tftio.DataTransferBegin(DATASIZE_16BIT); | ||||||
|       for (uint8_t i = 0; i < arg_val; i += 2) |       for (uint8_t i = 0; i < arg_val; i += 2) | ||||||
|         tftio.WriteData(*(uint16_t *)(((uint32_t)arg_ptr) + i)); |         tftio.WriteData(*(uint16_t *)(((uint32_t)arg_ptr) + i)); | ||||||
|       tftio.DataTransferEnd(); |       tftio.DataTransferEnd(); | ||||||
|   | |||||||
| @@ -274,6 +274,38 @@ | |||||||
|     #define FORCE_SOFT_SPI |     #define FORCE_SOFT_SPI | ||||||
|     #define LCD_BACKLIGHT_PIN              -1 |     #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 |   #else | ||||||
|  |  | ||||||
|     #define BTN_ENC                        P0_28  // (58) open-drain |     #define BTN_ENC                        P0_28  // (58) open-drain | ||||||
|   | |||||||
| @@ -1421,3 +1421,22 @@ | |||||||
| #if PIN_EXISTS(ESP_WIFI_MODULE_GPIO2) | #if PIN_EXISTS(ESP_WIFI_MODULE_GPIO2) | ||||||
|   REPORT_NAME_DIGITAL(__LINE__, ESP_WIFI_MODULE_GPIO2_PIN) |   REPORT_NAME_DIGITAL(__LINE__, ESP_WIFI_MODULE_GPIO2_PIN) | ||||||
| #endif | #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