TFT (plus Hardware SPI) for LPC (#19139)
This commit is contained in:
parent
4955aa5b78
commit
1a4b82a5d6
@ -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) {};
|
||||||
|
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; }
|
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 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:
|
||||||
|
/**
|
||||||
|
* @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();
|
void begin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the current SPI device
|
||||||
|
*/
|
||||||
|
void end();
|
||||||
|
|
||||||
void beginTransaction(const SPISettings&);
|
void beginTransaction(const SPISettings&);
|
||||||
void endTransaction() {};
|
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);
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user