TFT_COLOR_UI async DMA SPI (#24980)

This commit is contained in:
Alexander Gavrilenko 2022-12-13 00:13:31 +03:00 committed by Scott Lahteine
parent d082223fee
commit ec6349f2ac
31 changed files with 500 additions and 227 deletions

View File

@ -3132,6 +3132,10 @@
//#define TFT_COLOR_UI //#define TFT_COLOR_UI
//#define TFT_LVGL_UI //#define TFT_LVGL_UI
#if ENABLED(TFT_COLOR_UI)
//#define TFT_SHARED_SPI // SPI is shared between TFT display and other devices. Disable async data transfer
#endif
#if ENABLED(TFT_LVGL_UI) #if ENABLED(TFT_LVGL_UI)
//#define MKS_WIFI_MODULE // MKS WiFi module //#define MKS_WIFI_MODULE // MKS WiFi module
#endif #endif

View File

@ -318,8 +318,16 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
// Enable DMA // Enable DMA
GPDMA_ChannelCmd(0, ENABLE); GPDMA_ChannelCmd(0, ENABLE);
/*
* Observed behaviour on normal data transfer completion (SKR 1.3 board / LPC1768 MCU)
* GPDMA_STAT_INTTC flag is SET
* GPDMA_STAT_INTERR flag is NOT SET
* GPDMA_STAT_RAWINTTC flag is NOT SET
* GPDMA_STAT_RAWINTERR flag is SET
*/
// Wait for data transfer // Wait for data transfer
while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { } while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) {}
// Clear err and int // Clear err and int
GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0); GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
@ -333,6 +341,43 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE); SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
} }
void SPIClass::dmaSendAsync(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 = length;
// 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);
// Only increase memory if minc is true
GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
// Setup channel with given parameter
GPDMA_Setup(&GPDMACfg);
// Enable DMA
GPDMA_ChannelCmd(0, ENABLE);
}
uint16_t SPIClass::read() { uint16_t SPIClass::read() {
return SSP_ReceiveData(_currentSetting->spi_d); return SSP_ReceiveData(_currentSetting->spi_d);
} }

View File

@ -155,6 +155,7 @@ public:
void read(uint8_t *buf, uint32_t len); void read(uint8_t *buf, uint32_t len);
void dmaSend(void *buf, uint16_t length, bool minc); void dmaSend(void *buf, uint16_t length, bool minc);
void dmaSendAsync(void *buf, uint16_t length, bool minc);
/** /**
* @brief Sets the number of the SPI peripheral to be used by * @brief Sets the number of the SPI peripheral to be used by

View File

@ -26,7 +26,7 @@
#include "tft_spi.h" #include "tft_spi.h"
SPIClass TFT_SPI::SPIx(1); SPIClass TFT_SPI::SPIx(TFT_SPI_DEVICE);
void TFT_SPI::Init() { void TFT_SPI::Init() {
#if PIN_EXISTS(TFT_RESET) #if PIN_EXISTS(TFT_RESET)
@ -38,40 +38,10 @@ void TFT_SPI::Init() {
OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH); OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif #endif
SET_OUTPUT(TFT_DC_PIN); OUT_WRITE(TFT_DC_PIN, HIGH);
SET_OUTPUT(TFT_CS_PIN); OUT_WRITE(TFT_CS_PIN, HIGH);
WRITE(TFT_DC_PIN, HIGH);
WRITE(TFT_CS_PIN, HIGH);
/** SPIx.setModule(TFT_SPI_DEVICE);
* 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_TFT); SPIx.setClock(SPI_CLOCK_MAX_TFT);
SPIx.setBitOrder(MSBFIRST); SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0); SPIx.setDataMode(SPI_MODE0);
@ -114,17 +84,62 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
return data >> 7; return data >> 7;
} }
bool TFT_SPI::isBusy() { return false; } bool TFT_SPI::isBusy() {
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->DMACCSrcAddr != 0)
void TFT_SPI::Abort() { DataTransferEnd(); } // DMA Channel 0 is hardcoded in dmaSendAsync() and dmaSend()
if (!__IS_DMA_CONFIGURED(LPC_GPDMACH0)) return false;
void TFT_SPI::Transmit(uint16_t Data) { SPIx.transfer(Data); } if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) {
// You should not be here - DMA transfer error flag is set
// Abort DMA transfer and release SPI
}
else {
// Check if DMA transfer completed flag is set
if (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0)) return true;
// Check if SPI TX butter is empty and SPI is idle
if ((SSP_GetStatus(LPC_SSPx, SSP_STAT_TXFIFO_EMPTY) == RESET) || (SSP_GetStatus(LPC_SSPx, SSP_STAT_BUSY) == SET)) return true;
}
Abort();
return false;
}
void TFT_SPI::Abort() {
// DMA Channel 0 is hardcoded in dmaSendAsync() and dmaSend()
// Disable DMA
GPDMA_ChannelCmd(0, DISABLE);
// Clear ERR and TC
GPDMA_ClearIntPending(GPDMA_STATCLR_INTTC, 0);
GPDMA_ClearIntPending(GPDMA_STATCLR_INTERR, 0);
// Disable DMA on SPI
SSP_DMACmd(LPC_SSPx, SSP_DMA_TX, DISABLE);
// Deconfigure DMA Channel 0
LPC_GPDMACH0->DMACCControl = 0U;
LPC_GPDMACH0->DMACCConfig = 0U;
LPC_GPDMACH0->DMACCSrcAddr = 0U;
LPC_GPDMACH0->DMACCDestAddr = 0U;
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(DATASIZE_16BIT);
WRITE(TFT_DC_PIN, HIGH);
SPIx.dmaSend(Data, Count, MemoryIncrease);
DataTransferEnd(); DataTransferEnd();
} }
void TFT_SPI::Transmit(uint16_t Data) { SPIx.transfer(Data); }
void TFT_SPI::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(DATASIZE_16BIT);
SPIx.dmaSend(Data, Count, MemoryIncrease);
Abort();
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(DATASIZE_16BIT);
SPIx.dmaSendAsync(Data, Count, MemoryIncrease);
TERN_(TFT_SHARED_SPI, while (isBusy()));
}
#endif // HAS_SPI_TFT #endif // HAS_SPI_TFT

View File

@ -27,6 +27,18 @@
#include <lpc17xx_ssp.h> #include <lpc17xx_ssp.h>
// #include <lpc17xx_gpdma.h> // #include <lpc17xx_gpdma.h>
#define IS_SPI(N) (BOARD_NR_SPI >= N && (TFT_SCK_PIN == BOARD_SPI##N##_SCK_PIN) && (TFT_MOSI_PIN == BOARD_SPI##N##_MOSI_PIN) && (TFT_MISO_PIN == BOARD_SPI##N##_MISO_PIN))
#if IS_SPI(1)
#define TFT_SPI_DEVICE 1
#define LPC_SSPx LPC_SSP0
#elif IS_SPI(2)
#define TFT_SPI_DEVICE 2
#define LPC_SSPx LPC_SSP1
#else
#error "Invalid TFT SPI configuration."
#endif
#undef IS_SPI
#ifndef LCD_READ_ID #ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341) #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif #endif
@ -34,17 +46,19 @@
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341) #define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif #endif
#define DATASIZE_8BIT SSP_DATABIT_8 #define DATASIZE_8BIT SSP_DATABIT_8
#define DATASIZE_16BIT SSP_DATABIT_16 #define DATASIZE_16BIT SSP_DATABIT_16
#define TFT_IO_DRIVER TFT_SPI #define TFT_IO_DRIVER TFT_SPI
#define DMA_MAX_SIZE 0xFFF
#define DMA_MINC_ENABLE 1 #define DMA_MINC_ENABLE 1
#define DMA_MINC_DISABLE 0 #define DMA_MINC_DISABLE 0
class TFT_SPI { class TFT_SPI {
private: private:
static uint32_t ReadID(uint16_t Reg); static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data); static void Transmit(uint16_t Data);
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public: public:
@ -56,22 +70,20 @@ public:
static void Abort(); static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT); static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); }; static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); SSP_Cmd(LPC_SSPx, DISABLE); };
static void DataTransferAbort(); static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); } 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 WriteReg(uint16_t Reg) { WRITE(TFT_DC_PIN, LOW); Transmit(Reg); WRITE(TFT_DC_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); } static void WriteSequence_DMA(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_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t 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) { while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count); Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
#undef MAX_DMA_SIZE
} }
}; };

View File

@ -44,9 +44,11 @@ uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
#endif #endif
void XPT2046::Init() { void XPT2046::Init() {
SET_INPUT(TOUCH_MISO_PIN); #if DISABLED(TOUCH_BUTTONS_HW_SPI)
SET_OUTPUT(TOUCH_MOSI_PIN); SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_SCK_PIN); SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
#endif
OUT_WRITE(TOUCH_CS_PIN, HIGH); OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT) #if PIN_EXISTS(TOUCH_INT)

View File

@ -148,20 +148,35 @@ uint32_t TFT_FSMC::ReadID(tft_data_t Reg) {
bool TFT_FSMC::isBusy() { bool TFT_FSMC::isBusy() {
#ifdef STM32F1xx #ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET; #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->CPAR != 0)
#elif defined(STM32F4xx) #elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN; #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->PAR != 0)
#endif #endif
if (dmaEnabled) {
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0) if (!__IS_DMA_CONFIGURED(&DMAtx)) return false;
Abort();
} // Check if DMA transfer error or transfer complete flags are set
else if ((__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) == 0) && (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) == 0)) return true;
Abort();
return dmaEnabled; __DSB();
Abort();
return false;
}
void TFT_FSMC::Abort() {
HAL_DMA_Abort(&DMAtx); // Abort DMA transfer if any
HAL_DMA_DeInit(&DMAtx); // Deconfigure DMA
} }
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.PeriphInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx);
HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(LCD->RAM), Count);
}
void TFT_FSMC::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.PeriphInc = MemoryIncrease; DMAtx.Init.PeriphInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx); HAL_DMA_Init(&DMAtx);
DataTransferBegin(); DataTransferBegin();

View File

@ -41,6 +41,7 @@
#define DATASIZE_8BIT SPI_DATASIZE_8BIT #define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT #define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO_DRIVER TFT_FSMC #define TFT_IO_DRIVER TFT_FSMC
#define DMA_MAX_SIZE 0xFFFF
#define TFT_DATASIZE TERN(TFT_INTERFACE_FSMC_8BIT, DATASIZE_8BIT, DATASIZE_16BIT) #define TFT_DATASIZE TERN(TFT_INTERFACE_FSMC_8BIT, DATASIZE_8BIT, DATASIZE_16BIT)
typedef TERN(TFT_INTERFACE_FSMC_8BIT, uint8_t, uint16_t) tft_data_t; typedef TERN(TFT_INTERFACE_FSMC_8BIT, uint8_t, uint16_t) tft_data_t;
@ -59,13 +60,14 @@ class TFT_FSMC {
static uint32_t ReadID(tft_data_t Reg); static uint32_t ReadID(tft_data_t Reg);
static void Transmit(tft_data_t Data) { LCD->RAM = Data; __DSB(); } static void Transmit(tft_data_t Data) { LCD->RAM = Data; __DSB(); }
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public: public:
static void Init(); static void Init();
static uint32_t GetID(); static uint32_t GetID();
static bool isBusy(); static bool isBusy();
static void Abort() { __HAL_DMA_DISABLE(&DMAtx); } static void Abort();
static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {} static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {}
static void DataTransferEnd() {}; static void DataTransferEnd() {};
@ -73,13 +75,14 @@ class TFT_FSMC {
static void WriteData(uint16_t Data) { Transmit(tft_data_t(Data)); } static void WriteData(uint16_t Data) { Transmit(tft_data_t(Data)); }
static void WriteReg(uint16_t Reg) { LCD->REG = tft_data_t(Reg); __DSB(); } static void WriteReg(uint16_t Reg) { LCD->REG = tft_data_t(Reg); __DSB(); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); } static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); } static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) { static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) { while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count); Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
} }
}; };

View File

@ -356,7 +356,7 @@ void TFT_LTDC::WriteReg(uint16_t Reg) {
reg = Reg; reg = Reg;
} }
void TFT_LTDC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_LTDC::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
while (x_cur != x_min && Count) { while (x_cur != x_min && Count) {
Transmit(*Data); Transmit(*Data);

View File

@ -32,6 +32,7 @@
#define DATASIZE_8BIT SPI_DATASIZE_8BIT #define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT #define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO_DRIVER TFT_LTDC #define TFT_IO_DRIVER TFT_LTDC
#define DMA_MAX_SIZE 0xFFFF
#define TFT_DATASIZE DATASIZE_16BIT #define TFT_DATASIZE DATASIZE_16BIT
typedef uint16_t tft_data_t; typedef uint16_t tft_data_t;
@ -49,7 +50,7 @@ class TFT_LTDC {
static void DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color); static void DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);
static void DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors); static void DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors);
static void Transmit(tft_data_t Data); static void Transmit(tft_data_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public: public:
static void Init(); static void Init();
@ -63,13 +64,15 @@ class TFT_LTDC {
static void WriteData(uint16_t Data); static void WriteData(uint16_t Data);
static void WriteReg(uint16_t Reg); static void WriteReg(uint16_t Reg);
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); } // Non-blocking DMA data transfer is not implemented for LTDC interface
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); } inline static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { WriteSequence(Data, Count); }
inline static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { WriteMultiple(Color, Count); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) { static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) { while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count); Transmit(DMA_PINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
} }
}; };

View File

@ -160,16 +160,13 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
#if TFT_MISO_PIN != TFT_MOSI_PIN #if TFT_MISO_PIN != TFT_MOSI_PIN
//if (hspi->Init.Direction == SPI_DIRECTION_2LINES) { while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {} SPIx.Instance->DR = 0;
SPIx.Instance->DR = 0;
//}
#endif #endif
while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_RXNE)) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_RXNE)) {}
Data = (Data << 8) | SPIx.Instance->DR; Data = (Data << 8) | SPIx.Instance->DR;
} }
__HAL_SPI_DISABLE(&SPIx);
DataTransferEnd(); DataTransferEnd();
SPIx.Init.BaudRatePrescaler = BaudRatePrescaler; SPIx.Init.BaudRatePrescaler = BaudRatePrescaler;
@ -180,35 +177,43 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
bool TFT_SPI::isBusy() { bool TFT_SPI::isBusy() {
#ifdef STM32F1xx #ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET; #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->CPAR != 0)
#elif defined(STM32F4xx) #elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN; #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->PAR != 0)
#endif #endif
if (dmaEnabled) {
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0) if (!__IS_DMA_CONFIGURED(&DMAtx)) return false;
Abort();
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx))) {
// You should not be here - DMA transfer error flag is set
// Abort DMA transfer and release SPI
} }
else else {
Abort(); // Check if DMA transfer completed flag is set
return dmaEnabled; if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) == 0) return true;
// Check if SPI transmit butter is empty and SPI is idle
if ((!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) || (__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY))) return true;
}
Abort();
return false;
} }
void TFT_SPI::Abort() { void TFT_SPI::Abort() {
// Wait for any running spi HAL_DMA_Abort(&DMAtx); // Abort DMA transfer if any
while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
// First, abort any running dma
HAL_DMA_Abort(&DMAtx);
// DeInit objects
HAL_DMA_DeInit(&DMAtx); HAL_DMA_DeInit(&DMAtx);
HAL_SPI_DeInit(&SPIx);
// Deselect CS CLEAR_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN);
DataTransferEnd();
DataTransferEnd(); // Stop SPI and deselect CS
} }
void TFT_SPI::Transmit(uint16_t Data) { void TFT_SPI::Transmit(uint16_t Data) {
if (TFT_MISO_PIN == TFT_MOSI_PIN) #if TFT_MISO_PIN == TFT_MOSI_PIN
SPI_1LINE_TX(&SPIx); SPI_1LINE_TX(&SPIx);
#endif
__HAL_SPI_ENABLE(&SPIx); __HAL_SPI_ENABLE(&SPIx);
@ -217,14 +222,31 @@ void TFT_SPI::Transmit(uint16_t Data) {
while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {} while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {}
while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {} while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {}
if (TFT_MISO_PIN != TFT_MOSI_PIN) #if TFT_MISO_PIN != TFT_MOSI_PIN
__HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read __HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received data is not read
#endif
} }
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
// Wait last dma finish, to start another DMAtx.Init.MemInc = MemoryIncrease;
while (isBusy()) { /* nada */ } HAL_DMA_Init(&DMAtx);
#if TFT_MISO_PIN == TFT_MOSI_PIN
SPI_1LINE_TX(&SPIx);
#endif
DataTransferBegin();
HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(SPIx.Instance->DR), Count);
__HAL_SPI_ENABLE(&SPIx);
SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request
TERN_(TFT_SHARED_SPI, while (isBusy()));
}
void TFT_SPI::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.MemInc = MemoryIncrease; DMAtx.Init.MemInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx); HAL_DMA_Init(&DMAtx);
@ -243,7 +265,6 @@ void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Coun
} }
#if ENABLED(USE_SPI_DMA_TC) #if ENABLED(USE_SPI_DMA_TC)
void TFT_SPI::TransmitDMA_IT(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_SPI::TransmitDMA_IT(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.MemInc = MemoryIncrease; DMAtx.Init.MemInc = MemoryIncrease;
@ -262,8 +283,7 @@ void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Coun
SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request
} }
extern "C" void DMA2_Stream3_IRQHandler(void) { HAL_DMA_IRQHandler(&TFT_SPI::DMAtx); } extern "C" void DMA2_Stream3_IRQHandler(void) { TFT_SPI::DMA_IRQHandler(); }
#endif #endif
#endif // HAS_SPI_TFT #endif // HAS_SPI_TFT

View File

@ -39,46 +39,47 @@
#define DATASIZE_8BIT SPI_DATASIZE_8BIT #define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT #define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO_DRIVER TFT_SPI #define TFT_IO_DRIVER TFT_SPI
#define DMA_MAX_SIZE 0xFFFF
class TFT_SPI { class TFT_SPI {
private: private:
static SPI_HandleTypeDef SPIx; static SPI_HandleTypeDef SPIx;
static DMA_HandleTypeDef DMAtx;
static uint32_t ReadID(uint16_t Reg); static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data); static void Transmit(uint16_t Data);
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
#if ENABLED(USE_SPI_DMA_TC) #if ENABLED(USE_SPI_DMA_TC)
static void TransmitDMA_IT(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA_IT(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
#endif #endif
public: public:
static DMA_HandleTypeDef DMAtx;
static void Init(); static void Init();
static uint32_t GetID(); static uint32_t GetID();
static bool isBusy(); static bool isBusy();
static void Abort(); static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT); static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); }; static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); __HAL_SPI_DISABLE(&SPIx); };
static void DataTransferAbort(); static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); } static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { WRITE(TFT_A0_PIN, LOW); Transmit(Reg); WRITE(TFT_A0_PIN, HIGH); } static void WriteReg(uint16_t Reg) { WRITE(TFT_A0_PIN, LOW); Transmit(Reg); WRITE(TFT_A0_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); } static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
#if ENABLED(USE_SPI_DMA_TC) #if ENABLED(USE_SPI_DMA_TC)
static void WriteSequenceIT(uint16_t *Data, uint16_t Count) { TransmitDMA_IT(DMA_MINC_ENABLE, Data, Count); } static void WriteSequenceIT(uint16_t *Data, uint16_t Count) { TransmitDMA_IT(DMA_MINC_ENABLE, Data, Count); }
inline static void DMA_IRQHandler() { HAL_DMA_IRQHandler(&TFT_SPI::DMAtx); }
#endif #endif
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); } static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) { static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) { while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count); Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
} }
}; };

View File

@ -526,23 +526,22 @@ void SPIClass::onReceive(void(*callback)()) {
_currentSetting->receiveCallback = callback; _currentSetting->receiveCallback = callback;
if (callback) { if (callback) {
switch (_currentSetting->spi_d->clk_id) { switch (_currentSetting->spi_d->clk_id) {
#if BOARD_NR_SPI >= 1 #if BOARD_NR_SPI >= 1
case RCC_SPI1: case RCC_SPI1:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi1EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi1EventCallback);
break; break;
#endif #endif
#if BOARD_NR_SPI >= 2 #if BOARD_NR_SPI >= 2
case RCC_SPI2: case RCC_SPI2:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi2EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi2EventCallback);
break; break;
#endif #endif
#if BOARD_NR_SPI >= 3 #if BOARD_NR_SPI >= 3
case RCC_SPI3: case RCC_SPI3:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi3EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi3EventCallback);
break; break;
#endif #endif
default: default: ASSERT(0);
ASSERT(0);
} }
} }
else { else {
@ -554,23 +553,22 @@ void SPIClass::onTransmit(void(*callback)()) {
_currentSetting->transmitCallback = callback; _currentSetting->transmitCallback = callback;
if (callback) { if (callback) {
switch (_currentSetting->spi_d->clk_id) { switch (_currentSetting->spi_d->clk_id) {
#if BOARD_NR_SPI >= 1 #if BOARD_NR_SPI >= 1
case RCC_SPI1: case RCC_SPI1:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi1EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi1EventCallback);
break; break;
#endif #endif
#if BOARD_NR_SPI >= 2 #if BOARD_NR_SPI >= 2
case RCC_SPI2: case RCC_SPI2:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi2EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi2EventCallback);
break; break;
#endif #endif
#if BOARD_NR_SPI >= 3 #if BOARD_NR_SPI >= 3
case RCC_SPI3: case RCC_SPI3:
dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi3EventCallback); dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi3EventCallback);
break; break;
#endif #endif
default: default: ASSERT(0);
ASSERT(0);
} }
} }
else { else {

View File

@ -33,6 +33,15 @@
#include <stdint.h> #include <stdint.h>
#include <wirish.h> #include <wirish.h>
// Number of SPI ports
#ifdef BOARD_SPI3_SCK_PIN
#define BOARD_NR_SPI 3
#elif defined(BOARD_SPI2_SCK_PIN)
#define BOARD_NR_SPI 2
#elif defined(BOARD_SPI1_SCK_PIN)
#define BOARD_NR_SPI 1
#endif
// SPI_HAS_TRANSACTION means SPI has // SPI_HAS_TRANSACTION means SPI has
// - beginTransaction() // - beginTransaction()
// - endTransaction() // - endTransaction()

View File

@ -215,22 +215,47 @@ uint32_t TFT_FSMC::GetID() {
} }
bool TFT_FSMC::isBusy() { bool TFT_FSMC::isBusy() {
#define __IS_DMA_CONFIGURED(__DMAx__, __CHx__) (dma_channel_regs(__DMAx__, __CHx__)->CPAR != 0)
if (!__IS_DMA_CONFIGURED(FSMC_DMA_DEV, FSMC_DMA_CHANNEL)) return false;
// Check if DMA transfer error or transfer complete flags are set
if ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & (DMA_ISR_TCIF | DMA_ISR_TEIF)) == 0) return true;
__DSB();
Abort();
return false; return false;
} }
void TFT_FSMC::Abort() { void TFT_FSMC::Abort() {
dma_channel_reg_map *channel_regs = dma_channel_regs(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL); // Abort DMA transfer if any
// Deconfigure DMA
channel_regs->CCR = 0U;
channel_regs->CNDTR = 0U;
channel_regs->CMAR = 0U;
channel_regs->CPAR = 0U;
} }
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
// TODO: HAL STM32 uses DMA2_Channel1 for FSMC on STM32F1
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | MemoryIncrease);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Count);
dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
}
void TFT_FSMC::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
#if defined(FSMC_DMA_DEV) && defined(FSMC_DMA_CHANNEL) #if defined(FSMC_DMA_DEV) && defined(FSMC_DMA_CHANNEL)
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | MemoryIncrease); dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | MemoryIncrease);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Count); dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Count);
dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL); dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL); dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
while ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & 0x0A) == 0) {}; while ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & (DMA_CCR_TEIE | DMA_CCR_TCIE)) == 0) {}
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL); Abort();
#endif #endif
} }

View File

@ -33,6 +33,10 @@
#define DATASIZE_8BIT DMA_SIZE_8BITS #define DATASIZE_8BIT DMA_SIZE_8BITS
#define DATASIZE_16BIT DMA_SIZE_16BITS #define DATASIZE_16BIT DMA_SIZE_16BITS
#define TFT_IO_DRIVER TFT_FSMC #define TFT_IO_DRIVER TFT_FSMC
#define DMA_MAX_SIZE 0xFFFF
#define DMA_PINC_ENABLE DMA_PINC_MODE
#define DMA_PINC_DISABLE 0
typedef struct { typedef struct {
__IO uint16_t REG; __IO uint16_t REG;
@ -45,6 +49,7 @@ class TFT_FSMC {
static uint32_t ReadID(uint16_t Reg); static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data); static void Transmit(uint16_t Data);
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public: public:
@ -59,13 +64,14 @@ class TFT_FSMC {
static void WriteData(uint16_t Data) { Transmit(Data); } static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg); static void WriteReg(uint16_t Reg);
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_MODE, Data, Count); } static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_CIRC_MODE, &Data, Count); } static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) { static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) { while (Count > 0) {
TransmitDMA(DMA_CIRC_MODE, &Data, Count > 0xFFFF ? 0xFFFF : Count); Transmit(DMA_PINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
} }
}; };

View File

@ -26,7 +26,7 @@
#include "tft_spi.h" #include "tft_spi.h"
SPIClass TFT_SPI::SPIx(1); SPIClass TFT_SPI::SPIx(TFT_SPI_DEVICE);
void TFT_SPI::Init() { void TFT_SPI::Init() {
#if PIN_EXISTS(TFT_RESET) #if PIN_EXISTS(TFT_RESET)
@ -46,7 +46,7 @@ void TFT_SPI::Init() {
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1 * STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2 * so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
*/ */
#if SPI_DEVICE == 1 #if TFT_SPI_DEVICE == 1
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4 #define SPI_CLOCK_MAX SPI_CLOCK_DIV4
#else #else
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2 #define SPI_CLOCK_MAX SPI_CLOCK_DIV2
@ -62,7 +62,7 @@ void TFT_SPI::Init() {
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break; case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
} }
SPIx.setModule(1); SPIx.setModule(TFT_SPI_DEVICE);
SPIx.setClockDivider(clock); SPIx.setClockDivider(clock);
SPIx.setBitOrder(MSBFIRST); SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0); SPIx.setDataMode(SPI_MODE0);
@ -71,7 +71,7 @@ void TFT_SPI::Init() {
void TFT_SPI::DataTransferBegin(uint16_t DataSize) { void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
SPIx.setDataSize(DataSize); SPIx.setDataSize(DataSize);
SPIx.begin(); SPIx.begin();
OUT_WRITE(TFT_CS_PIN, LOW); WRITE(TFT_CS_PIN, LOW);
} }
#ifdef TFT_DEFAULT_DRIVER #ifdef TFT_DEFAULT_DRIVER
@ -113,15 +113,53 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
#endif #endif
} }
bool TFT_SPI::isBusy() { return false; } bool TFT_SPI::isBusy() {
#define __IS_DMA_CONFIGURED(__DMAx__, __CHx__) (dma_channel_regs(__DMAx__, __CHx__)->CPAR != 0)
void TFT_SPI::Abort() { DataTransferEnd(); } if (!__IS_DMA_CONFIGURED(DMAx, DMA_CHx)) return false;
if (dma_get_isr_bits(DMAx, DMA_CHx) & DMA_ISR_TEIF) {
// You should not be here - DMA transfer error flag is set
// Abort DMA transfer and release SPI
}
else {
// Check if DMA transfer completed flag is set
if (!(dma_get_isr_bits(DMAx, DMA_CHx) & DMA_ISR_TCIF)) return true;
// Check if SPI TX butter is empty and SPI is idle
if (!(SPIdev->regs->SR & SPI_SR_TXE) || (SPIdev->regs->SR & SPI_SR_BSY)) return true;
}
Abort();
return false;
}
void TFT_SPI::Abort() {
dma_channel_reg_map *channel_regs = dma_channel_regs(DMAx, DMA_CHx);
dma_disable(DMAx, DMA_CHx); // Abort DMA transfer if any
spi_tx_dma_disable(SPIdev);
// Deconfigure DMA
channel_regs->CCR = 0U;
channel_regs->CNDTR = 0U;
channel_regs->CMAR = 0U;
channel_regs->CPAR = 0U;
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) { SPIx.send(Data); } void TFT_SPI::Transmit(uint16_t Data) { SPIx.send(Data); }
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) { void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(); DataTransferBegin();
OUT_WRITE(TFT_DC_PIN, HIGH); SPIx.dmaSendAsync(Data, Count, MemoryIncrease == DMA_MINC_ENABLE);
TERN_(TFT_SHARED_SPI, while (isBusy()));
}
void TFT_SPI::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
WRITE(TFT_DC_PIN, HIGH);
DataTransferBegin();
SPIx.dmaSend(Data, Count, MemoryIncrease == DMA_MINC_ENABLE); SPIx.dmaSend(Data, Count, MemoryIncrease == DMA_MINC_ENABLE);
DataTransferEnd(); DataTransferEnd();
} }

View File

@ -25,6 +25,27 @@
#include <SPI.h> #include <SPI.h>
#define IS_SPI(N) (BOARD_NR_SPI >= N && (TFT_SCK_PIN == BOARD_SPI##N##_SCK_PIN) && (TFT_MOSI_PIN == BOARD_SPI##N##_MOSI_PIN) && (TFT_MISO_PIN == BOARD_SPI##N##_MISO_PIN))
#if IS_SPI(1)
#define TFT_SPI_DEVICE 1
#define SPIdev SPI1
#define DMAx DMA1
#define DMA_CHx DMA_CH3
#elif IS_SPI(2)
#define TFT_SPI_DEVICE 2
#define SPIdev SPI2
#define DMAx DMA1
#define DMA_CHx DMA_CH5
#elif IS_SPI(3)
#define TFT_SPI_DEVICE 3
#define SPIdev SPI3
#define DMAx DMA2
#define DMA_CHx DMA_CH2
#else
#error "Invalid TFT SPI configuration."
#endif
#undef IS_SPI
#ifndef LCD_READ_ID #ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341) #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif #endif
@ -32,17 +53,19 @@
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341) #define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif #endif
#define DATASIZE_8BIT DATA_SIZE_8BIT #define DATASIZE_8BIT DATA_SIZE_8BIT
#define DATASIZE_16BIT DATA_SIZE_16BIT #define DATASIZE_16BIT DATA_SIZE_16BIT
#define TFT_IO_DRIVER TFT_SPI #define TFT_IO_DRIVER TFT_SPI
#define DMA_MAX_SIZE 0xFFFF
#define DMA_MINC_ENABLE 1 #define DMA_MINC_ENABLE DMA_MINC_MODE
#define DMA_MINC_DISABLE 0 #define DMA_MINC_DISABLE 0
class TFT_SPI { class TFT_SPI {
private: private:
static uint32_t ReadID(uint16_t Reg); static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data); static void Transmit(uint16_t Data);
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count); static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public: public:
@ -58,15 +81,16 @@ public:
static void DataTransferAbort(); static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); } static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { WRITE(TFT_A0_PIN, LOW); Transmit(Reg); WRITE(TFT_A0_PIN, HIGH); } static void WriteReg(uint16_t Reg) { WRITE(TFT_DC_PIN, LOW); Transmit(Reg); WRITE(TFT_DC_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); } static void WriteSequence_DMA(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_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) { static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) { while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count); Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0; Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
} }
} }
}; };

View File

@ -65,9 +65,9 @@
#endif #endif
#endif #endif
#if TFT_BUFFER_SIZE > 65535 #if TFT_BUFFER_SIZE > DMA_MAX_SIZE
// DMA Count parameter is uint16_t // DMA Count parameter is uint16_t
#error "TFT_BUFFER_SIZE can not exceed 65535" #error "TFT_BUFFER_SIZE can not exceed DMA_MAX_SIZE"
#endif #endif
class TFT { class TFT {
@ -86,8 +86,8 @@ class TFT {
static bool is_busy() { return io.isBusy(); } static bool is_busy() { return io.isBusy(); }
static void abort() { io.Abort(); } static void abort() { io.Abort(); }
static void write_multiple(uint16_t Data, uint16_t Count) { io.WriteMultiple(Data, Count); } static void write_multiple(uint16_t Data, uint16_t Count) { io.WriteMultipleDMA(Data, Count); }
static void write_sequence(uint16_t *Data, uint16_t Count) { io.WriteSequence(Data, Count); } static void write_sequence(uint16_t *Data, uint16_t Count) { io.WriteSequenceDMA(Data, Count); }
static void set_window(uint16_t Xmin, uint16_t Ymin, uint16_t Xmax, uint16_t Ymax) { io.set_window(Xmin, Ymin, Xmax, Ymax); } static void set_window(uint16_t Xmin, uint16_t Ymin, uint16_t Xmax, uint16_t Ymax) { io.set_window(Xmin, Ymin, Xmax, Ymax); }
static void fill(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) { queue.fill(x, y, width, height, color); } static void fill(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) { queue.fill(x, y, width, height, color); }

View File

@ -86,9 +86,9 @@ void TFT_Queue::fill(queueTask_t *task) {
task->state = TASK_STATE_IN_PROGRESS; task->state = TASK_STATE_IN_PROGRESS;
} }
if (task_parameters->count > 65535) { if (task_parameters->count > DMA_MAX_SIZE) {
count = 65535; count = DMA_MAX_SIZE;
task_parameters->count -= 65535; task_parameters->count -= DMA_MAX_SIZE;
} }
else { else {
count = task_parameters->count; count = task_parameters->count;

View File

@ -135,6 +135,7 @@ class TFT_Queue {
static void reset(); static void reset();
static void async(); static void async();
static void sync() { while (current_task != nullptr) async(); } static void sync() { while (current_task != nullptr) async(); }
static bool is_empty() { return current_task == nullptr; }
static void fill(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color); static void fill(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
static void canvas(uint16_t x, uint16_t y, uint16_t width, uint16_t height); static void canvas(uint16_t x, uint16_t y, uint16_t width, uint16_t height);

View File

@ -57,7 +57,8 @@ void MarlinUI::tft_idle() {
#endif #endif
tft.queue.async(); tft.queue.async();
TERN_(TOUCH_SCREEN, touch.idle());
TERN_(TOUCH_SCREEN, if (tft.queue.is_empty()) touch.idle()); // Touch driver is not DMA-aware, so only check for touch controls after screen drawing is completed
} }
#if ENABLED(SHOW_BOOTSCREEN) #if ENABLED(SHOW_BOOTSCREEN)
@ -325,7 +326,10 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
add_control(900, y, menu_main, imgSettings); add_control(900, y, menu_main, imgSettings);
TERN_(SDSUPPORT, add_control(12, y, menu_media, imgSD, !printingIsActive(), COLOR_CONTROL_ENABLED, card.isMounted() && printingIsActive() ? COLOR_BUSY : COLOR_CONTROL_DISABLED)); #if ENABLED(SDSUPPORT)
const bool cm = card.isMounted(), pa = printingIsActive();
add_control(12, y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, cm && pa ? COLOR_BUSY : COLOR_CONTROL_DISABLED);
#endif
#endif #endif
y += 100; y += 100;

View File

@ -57,7 +57,8 @@ void MarlinUI::tft_idle() {
#endif #endif
tft.queue.async(); tft.queue.async();
TERN_(TOUCH_SCREEN, touch.idle());
TERN_(TOUCH_SCREEN, if (tft.queue.is_empty()) touch.idle()); // Touch driver is not DMA-aware, so only check for touch controls after screen drawing is completed
} }
#if ENABLED(SHOW_BOOTSCREEN) #if ENABLED(SHOW_BOOTSCREEN)
@ -342,7 +343,10 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
add_control(256, 130, menu_main, imgSettings); add_control(256, 130, menu_main, imgSettings);
TERN_(SDSUPPORT, add_control(0, 130, menu_media, imgSD, !printingIsActive(), COLOR_CONTROL_ENABLED, card.isMounted() && printingIsActive() ? COLOR_BUSY : COLOR_CONTROL_DISABLED)); #if ENABLED(SDSUPPORT)
const bool cm = card.isMounted(), pa = printingIsActive();
add_control(0, 130, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, cm && pa ? COLOR_BUSY : COLOR_CONTROL_DISABLED);
#endif
#endif #endif
} }

View File

@ -57,7 +57,8 @@ void MarlinUI::tft_idle() {
#endif #endif
tft.queue.async(); tft.queue.async();
TERN_(TOUCH_SCREEN, touch.idle());
TERN_(TOUCH_SCREEN, if (tft.queue.is_empty()) touch.idle()); // Touch driver is not DMA-aware, so only check for touch controls after screen drawing is completed
} }
#if ENABLED(SHOW_BOOTSCREEN) #if ENABLED(SHOW_BOOTSCREEN)
@ -319,7 +320,10 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
add_control(404, y, menu_main, imgSettings); add_control(404, y, menu_main, imgSettings);
TERN_(SDSUPPORT, add_control(12, y, menu_media, imgSD, !printingIsActive(), COLOR_CONTROL_ENABLED, card.isMounted() && printingIsActive() ? COLOR_BUSY : COLOR_CONTROL_DISABLED)); #if ENABLED(SDSUPPORT)
const bool cm = card.isMounted(), pa = printingIsActive();
add_control(12, y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, cm && pa ? COLOR_BUSY : COLOR_CONTROL_DISABLED);
#endif
#endif #endif
y += TERN(HAS_UI_480x272, 36, 44); y += TERN(HAS_UI_480x272, 36, 44);

View File

@ -60,7 +60,7 @@ TFT_IO_DRIVER TFT_IO::io;
uint32_t TFT_IO::lcd_id = 0xFFFFFFFF; uint32_t TFT_IO::lcd_id = 0xFFFFFFFF;
void TFT_IO::InitTFT() { void TFT_IO::InitTFT() {
if (lcd_id != 0xFFFFFFFF) return; if (lcd_id != 0xFFFFFFFF) return;
#if PIN_EXISTS(TFT_BACKLIGHT) #if PIN_EXISTS(TFT_BACKLIGHT)
OUT_WRITE(TFT_BACKLIGHT_PIN, LOW); OUT_WRITE(TFT_BACKLIGHT_PIN, LOW);
@ -243,7 +243,7 @@ void TFT_IO::write_esc_sequence(const uint16_t *Sequence) {
continue; continue;
} }
data = *Sequence++; data = *Sequence++;
if (data == 0x7FFF) return; if (data == 0x7FFF) break;
if (data == 0xFFFF) if (data == 0xFFFF)
io.WriteData(0xFFFF); io.WriteData(0xFFFF);
else if (data & 0x8000) else if (data & 0x8000)

View File

@ -30,7 +30,11 @@
#elif HAS_LTDC_TFT #elif HAS_LTDC_TFT
#include HAL_PATH(../../HAL, tft/tft_ltdc.h) #include HAL_PATH(../../HAL, tft/tft_ltdc.h)
#else #else
#error "TFT IO only supports SPI, FSMC or LTDC interface" #error "TFT IO only supports SPI, FSMC or LTDC interface."
#endif
#ifndef DMA_MAX_SIZE
#error "MAX_DMA_SIZE is not configured for this platform."
#endif #endif
#define TFT_EXCHANGE_XY _BV32(1) #define TFT_EXCHANGE_XY _BV32(1)
@ -108,27 +112,33 @@ public:
static void write_esc_sequence(const uint16_t *Sequence); static void write_esc_sequence(const uint16_t *Sequence);
// Deletaged methods // Deletaged methods
inline static void Init() { io.Init(); io.Abort(); }; inline static void Init() { io.Init(); }
inline static bool isBusy() { return io.isBusy(); }; inline static bool isBusy() { return io.isBusy(); }
inline static void Abort() { io.Abort(); }; inline static void Abort() { io.Abort(); }
inline static uint32_t GetID() { return io.GetID(); }; inline static uint32_t GetID() { return io.GetID(); }
inline static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT) { io.DataTransferBegin(DataWidth); } inline static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT) { io.DataTransferBegin(DataWidth); }
inline static void DataTransferEnd() { io.DataTransferEnd(); }; inline static void DataTransferEnd() { io.DataTransferEnd(); }
// inline static void DataTransferAbort() { io.DataTransferAbort(); };
inline static void WriteData(uint16_t Data) { io.WriteData(Data); }; inline static void WriteData(uint16_t Data) { io.WriteData(Data); }
inline static void WriteReg(uint16_t Reg) { io.WriteReg(Reg); }; inline static void WriteReg(uint16_t Reg) { io.WriteReg(Reg); }
inline static void WriteSequence(uint16_t *Data, uint16_t Count) { io.WriteSequence(Data, Count); }; // Blocking IO used by TFT_CLASSIC_UI and TFT_LVGL_UI
// These functions start data transfer and WAIT for data transfer completion
inline static void WriteSequence(uint16_t *Data, uint16_t Count) { io.WriteSequence(Data, Count); }
inline static void WriteMultiple(uint16_t Color, uint32_t Count) { io.WriteMultiple(Color, Count); }
// Non-blocking DMA-based IO used by TFT_COLOR_UI only
// These functions start data transfer using DMA and do NOT wait for data transfer completion
inline static void WriteSequenceDMA(uint16_t *Data, uint16_t Count) { io.WriteSequence_DMA(Data, Count); }
inline static void WriteMultipleDMA(uint16_t Color, uint16_t Count) { io.WriteMultiple_DMA(Color, Count); }
// Non-blocking DMA-based IO with IRQ callback used by TFT_LVGL_UI only
// This function starts data transfer using DMA and does NOT wait for data transfer completion
#if ENABLED(USE_SPI_DMA_TC) #if ENABLED(USE_SPI_DMA_TC)
inline static void WriteSequenceIT(uint16_t *Data, uint16_t Count) { io.WriteSequenceIT(Data, Count); }; inline static void WriteSequenceIT(uint16_t *Data, uint16_t Count) { io.WriteSequenceIT(Data, Count); }
#endif #endif
// static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
inline static void WriteMultiple(uint16_t Color, uint32_t Count) { io.WriteMultiple(Color, Count); };
protected: protected:
static uint32_t lcd_id; static uint32_t lcd_id;
}; };

View File

@ -323,6 +323,9 @@
#define BTN_EN1 EXP2_03_PIN #define BTN_EN1 EXP2_03_PIN
#define BTN_ENC EXP1_02_PIN #define BTN_ENC EXP1_02_PIN
#define BEEPER_PIN EXP1_01_PIN
#define SDCARD_CONNECTION ONBOARD
#define TOUCH_BUTTONS_HW_SPI #define TOUCH_BUTTONS_HW_SPI
#define TOUCH_BUTTONS_HW_SPI_DEVICE 1 #define TOUCH_BUTTONS_HW_SPI_DEVICE 1

View File

@ -140,7 +140,38 @@
// //
// LCD / Controller // LCD / Controller
// //
#if HAS_WIRED_LCD #if EITHER(TFT_COLOR_UI, TFT_CLASSIC_UI)
#define BEEPER_PIN EXP1_01_PIN
#define BTN_ENC EXP1_02_PIN
#define BTN_EN1 EXP2_03_PIN
#define BTN_EN2 EXP2_05_PIN
#define TFT_CS_PIN EXP1_07_PIN
#define TFT_SCK_PIN EXP2_02_PIN
#define TFT_MISO_PIN EXP2_01_PIN
#define TFT_MOSI_PIN EXP2_06_PIN
#define TFT_DC_PIN EXP1_08_PIN
#define TFT_A0_PIN TFT_DC_PIN
#define TFT_RESET_PIN EXP1_04_PIN
#define LCD_BACKLIGHT_PIN EXP1_03_PIN
#define TFT_BACKLIGHT_PIN LCD_BACKLIGHT_PIN
#define TOUCH_BUTTONS_HW_SPI
#define TOUCH_BUTTONS_HW_SPI_DEVICE 3
#define TOUCH_CS_PIN EXP1_05_PIN // SPI3_NSS
#define TOUCH_SCK_PIN EXP2_02_PIN // SPI3_SCK
#define TOUCH_MISO_PIN EXP2_01_PIN // SPI3_MISO
#define TOUCH_MOSI_PIN EXP2_06_PIN // SPI3_MOSI
#define LCD_READ_ID 0xD3
#define LCD_USE_DMA_SPI
#define TFT_BUFFER_SIZE 9600
#elif HAS_WIRED_LCD
#define BEEPER_PIN EXP1_01_PIN #define BEEPER_PIN EXP1_01_PIN
#define BTN_ENC EXP1_02_PIN #define BTN_ENC EXP1_02_PIN
@ -253,5 +284,7 @@
#define SD_MOSI_PIN PA7 #define SD_MOSI_PIN PA7
#define SD_SS_PIN PA4 #define SD_SS_PIN PA4
#endif #endif
#define ONBOARD_SPI_DEVICE 1 // SPI1 #define ONBOARD_SPI_DEVICE 1 // SPI1
#define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card #define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card
#define SDSS SD_SS_PIN

View File

@ -63,7 +63,6 @@
* SPI3 is unusable due to pin 43 (PB4) and NRST tie-together :(, but * SPI3 is unusable due to pin 43 (PB4) and NRST tie-together :(, but
* leave the definitions so as not to clutter things up. This is only * leave the definitions so as not to clutter things up. This is only
* OK since RET6 Ed. is specifically advertised as a beta board. */ * OK since RET6 Ed. is specifically advertised as a beta board. */
#define BOARD_NR_SPI 3
#define BOARD_SPI1_NSS_PIN PA4 #define BOARD_SPI1_NSS_PIN PA4
#define BOARD_SPI1_SCK_PIN PA5 #define BOARD_SPI1_SCK_PIN PA5
#define BOARD_SPI1_MISO_PIN PA6 #define BOARD_SPI1_MISO_PIN PA6
@ -79,7 +78,6 @@
#define BOARD_SPI3_MISO_PIN PB4 #define BOARD_SPI3_MISO_PIN PB4
#define BOARD_SPI3_MOSI_PIN PB5 #define BOARD_SPI3_MOSI_PIN PB5
/* GPIO A to E = 5 * 16 - BOOT1 not used = 79*/ /* GPIO A to E = 5 * 16 - BOOT1 not used = 79*/
#define BOARD_NR_GPIO_PINS 112 #define BOARD_NR_GPIO_PINS 112
/* Note: NOT 19. The missing one is D38 a.k.a. BOARD_BUTTON_PIN, which /* Note: NOT 19. The missing one is D38 a.k.a. BOARD_BUTTON_PIN, which

View File

@ -63,26 +63,21 @@
* SPI3 is unusable due to pin 43 (PB4) and NRST tie-together :(, but * SPI3 is unusable due to pin 43 (PB4) and NRST tie-together :(, but
* leave the definitions so as not to clutter things up. This is only * leave the definitions so as not to clutter things up. This is only
* OK since RET6 Ed. is specifically advertised as a beta board. */ * OK since RET6 Ed. is specifically advertised as a beta board. */
#define BOARD_NR_SPI 3
#define BOARD_SPI1_NSS_PIN PA4 #define BOARD_SPI1_NSS_PIN PA4
#define BOARD_SPI1_SCK_PIN PA5 #define BOARD_SPI1_SCK_PIN PA5
#define BOARD_SPI1_MISO_PIN PA6 #define BOARD_SPI1_MISO_PIN PA6
#define BOARD_SPI1_MOSI_PIN PA7 #define BOARD_SPI1_MOSI_PIN PA7
#define BOARD_SPI2_NSS_PIN PB12 #define BOARD_SPI2_NSS_PIN PB12
#define BOARD_SPI2_SCK_PIN PB13 #define BOARD_SPI2_SCK_PIN PB13
#define BOARD_SPI2_MISO_PIN PB14 #define BOARD_SPI2_MISO_PIN PB14
#define BOARD_SPI2_MOSI_PIN PB15 #define BOARD_SPI2_MOSI_PIN PB15
#define BOARD_SPI3_NSS_PIN PA15 #define BOARD_SPI3_NSS_PIN PA15
#define BOARD_SPI3_SCK_PIN PB3 #define BOARD_SPI3_SCK_PIN PB3
#define BOARD_SPI3_MISO_PIN PB4 #define BOARD_SPI3_MISO_PIN PB4
#define BOARD_SPI3_MOSI_PIN PB5 #define BOARD_SPI3_MOSI_PIN PB5
/* GPIO A to E = 5 * 16 - BOOT1 not used = 79*/ /* GPIO A to E = 5 * 16 - BOOT1 not used = 79*/
#define BOARD_NR_GPIO_PINS 51 #define BOARD_NR_GPIO_PINS 51
/* Note: NOT 19. The missing one is D38 a.k.a. BOARD_BUTTON_PIN, which /* Note: NOT 19. The missing one is D38 a.k.a. BOARD_BUTTON_PIN, which

View File

@ -217,21 +217,21 @@ build_flags = ${STM32F1_maple.build_flags} -DMCU_STM32F103VE -DSS_TIMER
# MKS Robin (STM32F103ZET6) # MKS Robin (STM32F103ZET6)
# #
[env:mks_robin_maple] [env:mks_robin_maple]
extends = STM32F1_maple extends = STM32F1_maple
board = genericSTM32F103ZE board = genericSTM32F103ZE
board_build.address = 0x08007000 board_build.address = 0x08007000
board_build.rename = Robin.bin board_build.encrypt_mks = Robin.bin
board_build.ldscript = mks_robin.ld board_build.ldscript = mks_robin.ld
build_flags = ${STM32F1_maple.build_flags} -DSS_TIMER=4 -DSTM32_XL_DENSITY build_flags = ${STM32F1_maple.build_flags} -DSS_TIMER=4 -DSTM32_XL_DENSITY
# #
# MKS Robin Pro (STM32F103ZET6) # MKS Robin Pro (STM32F103ZET6)
# #
[env:mks_robin_pro_maple] [env:mks_robin_pro_maple]
extends = env:mks_robin_maple extends = env:mks_robin_maple
board_build.address = 0x08007000 board_build.address = 0x08007000
board_build.rename = Robin_pro.bin board_build.encrypt_mks = Robin_pro.bin
board_build.ldscript = mks_robin_pro.ld board_build.ldscript = mks_robin_pro.ld
# #
# TRIGORILLA PRO (STM32F103ZET6) # TRIGORILLA PRO (STM32F103ZET6)