From 22982db966ac7e66750ff3756b89466f7740ffd3 Mon Sep 17 00:00:00 2001 From: Attila BODY Date: Fri, 14 Feb 2020 19:39:15 +0100 Subject: [PATCH] Scroll pt. 1 --- App/application.cpp | 14 ++- F407_test.ioc | 4 +- components/f4ll_cpp/ili9341.cpp | 154 +++++++++++++++++++++----------- components/f4ll_cpp/ili9341.h | 27 ++++-- 4 files changed, 139 insertions(+), 60 deletions(-) diff --git a/App/application.cpp b/App/application.cpp index 85eea3d..11a2936 100644 --- a/App/application.cpp +++ b/App/application.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include #include "main.h" @@ -31,11 +32,18 @@ Application::Application() void Application::Loop() { + char buffer[32]; + Ili9341Fsmc &lcd(Ili9341Fsmc::Init(nullptr, nullptr, DMA2, LL_DMA_STREAM_4, false)); - lcd.FillRect(Ili9341Fsmc::ILI9341_ORANGE, false); - lcd.Test(); - lcd.Print("0 1 2 3 4 5 6 7 8 9 A B C D E F\r\n"); + lcd.FillRect(Ili9341Fsmc::ILI9341_BLACK, false); + + for(uint32_t l = 0; l < 100; ++l) { + uitodec(buffer, l); + lcd.Print(buffer); + lcd.Print("\r\n"); + } + for(;;) { if(m_received && m_transmitted) { diff --git a/F407_test.ioc b/F407_test.ioc index 49f142b..bb10119 100644 --- a/F407_test.ioc +++ b/F407_test.ioc @@ -36,9 +36,9 @@ Dma.USART1_TX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE Dma.USART1_TX.2.PeriphInc=DMA_PINC_DISABLE Dma.USART1_TX.2.Priority=DMA_PRIORITY_LOW Dma.USART1_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode -FSMC.AddressSetupTime1=0 +FSMC.AddressSetupTime1=1 FSMC.BusTurnAroundDuration1=0 -FSMC.DataSetupTime1=1 +FSMC.DataSetupTime1=4 FSMC.IPParameters=DataSetupTime1,AddressSetupTime1,BusTurnAroundDuration1 File.Version=6 KeepUserPlacement=false diff --git a/components/f4ll_cpp/ili9341.cpp b/components/f4ll_cpp/ili9341.cpp index 91e834f..75f724c 100644 --- a/components/f4ll_cpp/ili9341.cpp +++ b/components/f4ll_cpp/ili9341.cpp @@ -13,6 +13,8 @@ #define LCD_REG (*((volatile unsigned short *) 0x60000000)) /* DC = 0 */ #define LCD_RAM (*((volatile unsigned short *) 0x60080000)) /* DC = 1 */ +#define RGB2U16(R,G,B) ((R & 0xf8) << 8 | (G & 0xfc) << 3 | (B & 0xf8) >> 3) +#define SPLIT(x) ((uint8_t)(x >> 8)), ((uint8_t)x) Ili9341Fsmc::Ili9341Fsmc(volatile uint16_t *reg, volatile uint16_t *ram, DMA_TypeDef *dma, uint32_t dmaStream, @@ -56,6 +58,7 @@ Ili9341Fsmc::Ili9341Fsmc(volatile uint16_t *reg, volatile uint16_t *ram, WriteCmd(ILI9341_SLEEP_OUT); LL_mDelay(100); WriteCmd(ILI9341_DISPLAY_ON); + WriteCmd(ILI9341_VERTICAL_SCROLLING_DEFINITION, {0x00, 0x00, SPLIT(m_height), 0x00, 0x00}); } void Ili9341Fsmc::WriteCmd(uint16_t cmd, std::initializer_list params) @@ -77,6 +80,62 @@ void Ili9341Fsmc::WriteCmd_(uint16_t cmd, uint16_t cnt, ...) va_end(argp); } +void Ili9341Fsmc::WritePixels(void *src, uint32_t count, bool increment, bool async) +{ + WriteCmd(ILI9341_GRAM); + LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), (uint32_t)m_ram); + LL_DMA_SetMemoryIncMode(GetDma(), GetStream(), LL_DMA_MEMORY_NOINCREMENT); + LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), (uint32_t) src); + LL_DMA_SetPeriphIncMode(GetDma(), GetStream(), increment ? LL_DMA_PERIPH_NOINCREMENT : LL_DMA_PERIPH_NOINCREMENT); + SetupDmaSize(count); + m_dmaEngineBusy = true; + LL_DMA_EnableStream(GetDma(), GetStream()); + if(!async) + WaitDmaIdle(); +} + +void Ili9341Fsmc::ReadGRam(PixelPair *dst, uint32_t count, bool async) +{ + WriteCmd(ILI9341_MEMORY_READ); + *m_ram; + LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), reinterpret_cast(m_ram)); + LL_DMA_SetPeriphIncMode(GetDma(), GetStream(), LL_DMA_PERIPH_NOINCREMENT); + LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), reinterpret_cast(dst)); + LL_DMA_SetMemoryIncMode(GetDma(), GetStream(), LL_DMA_MEMORY_INCREMENT); + SetupDmaSize(count); + m_dmaEngineBusy = true; + LL_DMA_EnableStream(GetDma(), GetStream()); + if(!async) + WaitDmaIdle(); +} + +void Ili9341Fsmc::ReadPixels(uint16_t *dst, uint32_t count) +{ + uint16_t *barrier = dst + count; + union { + PixelPair pp; + uint16_t u16[3]; + } rawData; + + WriteCmd(ILI9341_MEMORY_READ); + *m_ram; + do { + for(uint8_t n = 0; n < 3; ++n) + rawData.u16[n] = *m_ram; + *dst++ = RGB2U16(rawData.pp.r0, rawData.pp.g0, rawData.pp.b0); + if(dst != barrier) + *dst++ = RGB2U16(rawData.pp.r1, rawData.pp.g1, rawData.pp.b1); + } while(dst != barrier); +} + +void Ili9341Fsmc::SetScrollOffset() +{ + uint16_t offsetData[2] = { SPLIT(m_scrollOffset) }; + WriteCmd(ILI9341_VERTICAL_SCROLLING_START_ADDRESS); + *m_ram = offsetData[0]; + *m_ram = offsetData[1]; +} + void Ili9341Fsmc::SetRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height) { if(x > m_width || y > m_height || !width || !height ) @@ -92,8 +151,8 @@ void Ili9341Fsmc::SetRect(uint16_t x, uint16_t y, uint16_t width, uint16_t heigh uint16_t right = x + m_rectWidth - 1; uint16_t bottom = y + m_rectHeight - 1; - WriteCmd(ILI9341_COLUMN_ADDR, {(uint16_t)(x >> 8), (uint16_t)(x & 0xff), (uint16_t)(right >> 8), (uint16_t)(right & 0xff)}); - WriteCmd(ILI9341_PAGE_ADDR, {(uint16_t)(y >> 8), (uint16_t)(y & 0xff), (uint16_t)(bottom >> 8), (uint16_t)(bottom & 0xff)}); + WriteCmd(ILI9341_COLUMN_ADDR, { SPLIT(x), SPLIT(right) }); + WriteCmd(ILI9341_PAGE_ADDR, { SPLIT(y), SPLIT(bottom) }); } void Ili9341Fsmc::FillRect(uint16_t color, bool async) @@ -101,16 +160,7 @@ void Ili9341Fsmc::FillRect(uint16_t color, bool async) uint32_t count = m_rectWidth * m_rectHeight; WaitDmaIdle(); m_dmaColor = color; - WriteCmd(ILI9341_GRAM); - LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), (uint32_t)m_ram); - LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), (uint32_t) &m_dmaColor); - LL_DMA_SetMemoryIncMode(GetDma(), GetStream(), LL_DMA_MEMORY_NOINCREMENT); - LL_DMA_SetPeriphIncMode(GetDma(), GetStream(), LL_DMA_PERIPH_NOINCREMENT); - SetupDmaSize(count); - m_dmaEngineBusy = true; - LL_DMA_EnableStream(GetDma(), GetStream()); - if(!async) - WaitDmaIdle(); + WritePixels(&m_dmaColor, count, false, async); } void Ili9341Fsmc::FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, bool async) @@ -132,8 +182,8 @@ void Ili9341Fsmc::SetupDmaSize(uint32_t size) void Ili9341Fsmc::HandleDmaIrq() { - if(*GetIsReg() & GetTcMask()) { //LL_DMA_IsActiveFlag_TC4(DMA2)) { - *GetIfcReg() = GetTcMask(); //LL_DMA_ClearFlag_TC4(DMA2); + if(*GetIsReg() & GetTcMask()) { //LL_DMA_IsActiveFlag_TCx(DMAy)) + *GetIfcReg() = GetTcMask(); //LL_DMA_ClearFlag_TCx(DMAy) LL_DMA_DisableStream(GetDma(), GetStream()); if(!m_dmaRemainingPixels) m_dmaEngineBusy = false; @@ -141,8 +191,8 @@ void Ili9341Fsmc::HandleDmaIrq() SetupDmaSize(m_dmaRemainingPixels); LL_DMA_EnableStream(GetDma(), GetStream()); } - } else if(*GetIsReg() & GetTeMask()) - *GetIfcReg() = GetTeMask(); + } else if(*GetIsReg() & GetTeMask()) //LL_DMA_IsActiveFlag_TEx(DMAy)) + *GetIfcReg() = GetTeMask(); // //LL_DMA_ClearFlag_TEx(DMAy) } void Ili9341Fsmc::SetCursor(uint16_t x, uint16_t y, uint16_t fgColor, uint16_t bgColor) @@ -153,33 +203,29 @@ void Ili9341Fsmc::SetCursor(uint16_t x, uint16_t y, uint16_t fgColor, uint16_t b m_bgColor = bgColor; } +void Ili9341Fsmc::SetCursor(uint16_t x, uint16_t y) +{ + m_xPos = x; + m_yPos = y; +} + void Ili9341Fsmc::PrintChar(char c, bool transparent) { // fonts are rotated, one byte representing one column - if(m_xPos >= m_width - CHRWIDTH || m_yPos >= m_height - CHRHEIGHT || c < ' ' || c >= '~') + if(m_xPos > m_width - CHRWIDTH || m_yPos > m_height - CHRHEIGHT || c < ' ' || c >= '~') return; uint8_t const *chrPtr = m_font[c - 32]; - SetRect(m_xPos, m_yPos, CHRWIDTH, CHRHEIGHT); - if(transparent) { - WaitDmaIdle(); - WriteCmd(ILI9341_MEMORY_READ); - *m_ram; - LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), reinterpret_cast(m_ram)); - LL_DMA_SetPeriphIncMode(GetDma(), GetStream(), LL_DMA_PERIPH_NOINCREMENT); - LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), reinterpret_cast(m_fontBuffer)); - LL_DMA_SetMemoryIncMode(GetDma(), GetStream(), LL_DMA_MEMORY_INCREMENT); - SetupDmaSize(sizeof(m_fontBuffer)/sizeof(m_fontBuffer[0][0])); - m_dmaEngineBusy = true; - LL_DMA_EnableStream(GetDma(), GetStream()); - } + SetRect(m_xPos, AdjustY(m_yPos), CHRWIDTH, CHRHEIGHT); WaitDmaIdle(); + if(transparent) + ReadPixels(m_fontBkgBuffer[0], CHRHEIGHT * CHRWIDTH); WriteCmd(ILI9341_GRAM); for(uint8_t y = 0; y < CHRHEIGHT; ++y ) { uint8_t mask = 1 << y; for(uint8_t x = 0; x < CHRWIDTH; ++x) { - *m_ram = (chrPtr[x] & mask) ? m_fgColor : (transparent ? m_fontBuffer[y][x] : m_bgColor); + *m_ram = (chrPtr[x] & mask) ? m_fgColor : (transparent ? m_fontBkgBuffer[y][x] : m_bgColor); } } m_xPos += CHRWIDTH; @@ -198,8 +244,18 @@ void Ili9341Fsmc::Print(char const *str, uint8_t len) while(len--) { if(*str == '\r') m_xPos = 0; - else if(*str == '\n') + else if(*str == '\n') { m_yPos += CHRHEIGHT; + if(m_yPos >= m_height) { + m_yPos -= CHRHEIGHT; + m_scrollOffset += CHRHEIGHT; + if(m_scrollOffset >= m_height) + m_scrollOffset -= m_height; + WaitDmaIdle(); + SetScrollOffset(); + FillRect(0, AdjustY(m_yPos), m_width, CHRHEIGHT, m_bgColor); + } + } else PrintChar(*str, false); ++str; @@ -208,27 +264,25 @@ void Ili9341Fsmc::Print(char const *str, uint8_t len) void Ili9341Fsmc::Test() { - static uint16_t linebuf[320]; - uint16_t x; +// static PixelPair linebuf[320/2]; +// uint16_t x; - WriteCmd(ILI9341_READ_ID4); - for( x= 0; x < 4; ++x) - linebuf[x] = *m_ram; - -// uint16_t *bufptr = linebuf; -// WriteCmd(ILI9341_MEMORY_READ); -// for(x = 0; x < m_width; ++x) -// *bufptr++ = *m_ram; +// WriteCmd(ILI9341_READ_DISPLAY_PIXEL_FORMAT); +// for( x= 0; x < 2; ++x) +// reinterpret_cast(linebuf)[x] = *m_ram; - WriteCmd(ILI9341_GRAM); - uint16_t fillers[4] = { 0xf800, 0x7e0, 0x1f, 0xffff }; - for(uint32_t y = 0; y < m_height; ++y) { - for(x = 0; x < m_width / 2; ++x) - *m_ram = fillers[ (x&0x18) >> 3 ]; - for( ; x < m_width; ++x) - *m_ram = 0; - } +// WriteCmd(ILI9341_GRAM); +// uint16_t fillers[4] = { 0xf800, 0x7e0, 0x1f, 0xffff }; +// for(uint32_t y = 0; y < m_height; ++y) { +// for(x = 0; x < m_width / 2; ++x) +// *m_ram = fillers[ (x&0x18) >> 3 ]; +// for( ; x < m_width; ++x) +// *m_ram = 0; +// } +// +// SetRect(0, 0, 11, 2); +// ReadGRam(linebuf, 11 * 3); } diff --git a/components/f4ll_cpp/ili9341.h b/components/f4ll_cpp/ili9341.h index e1eb4af..dc1df55 100644 --- a/components/f4ll_cpp/ili9341.h +++ b/components/f4ll_cpp/ili9341.h @@ -8,6 +8,10 @@ class Ili9341Fsmc : public Singleton, private DmaHelper { public: + struct PixelPair { + uint8_t g0, r0, r1, b0, b1, g1; + }; + Ili9341Fsmc(volatile uint16_t *reg, volatile uint16_t *ram, DMA_TypeDef *dma, uint32_t dmaStream, bool horizontal = true); @@ -16,7 +20,10 @@ public: void FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, bool async = true); uint16_t Width() { return m_width; } uint16_t Height() { return m_height; } + uint8_t ChrHeight() { return CHRHEIGHT; } + uint8_t ChrWidth() { return CHRWIDTH; } void SetCursor(uint16_t x, uint16_t y, uint16_t fgColor, uint16_t bgColor); + void SetCursor(uint16_t x, uint16_t y); void PrintChar(char c, uint16_t x, uint16_t y, uint16_t fgColor, uint16_t bgColor); void PrintChar(char c, bool transparent = false); void Print(char const *str, uint8_t len = 0); @@ -33,23 +40,32 @@ private: void WriteCmd(uint16_t cmd, std::initializer_list params); void WriteCmd_(uint16_t cmd, uint16_t cnt, ...); void SetRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height); + void WritePixels(void *src, uint32_t count, bool increment, bool async = true); + void ReadGRam(PixelPair *dst, uint32_t count, bool async = true); + void ReadPixels(uint16_t *dst, uint32_t count); + void SetScrollOffset(); volatile uint16_t * const m_reg; volatile uint16_t * const m_ram; void HandleDmaIrq(); void SetupDmaSize(uint32_t size); + uint16_t AdjustY(uint16_t y) { return (m_scrollOffset + y) % m_height; } + volatile bool m_dmaEngineBusy = false; uint32_t m_dmaRemainingPixels = 0; uint16_t m_dmaColor = 0; + + // initialized in the constructor uint16_t const m_width; uint16_t const m_height; + uint16_t m_rectX; + uint16_t m_rectY; + uint16_t m_rectWidth; + uint16_t m_rectHeight; - uint16_t m_rectX; - uint16_t m_rectY; - uint16_t m_rectWidth; - uint16_t m_rectHeight; + uint16_t m_scrollOffset = 0; uint16_t m_xPos = 0; uint16_t m_yPos = 0; @@ -141,7 +157,8 @@ private: static const uint8_t CHRWIDTH = 6; static const uint8_t CHRCOUNT = 96; static const uint8_t m_font[CHRCOUNT][CHRWIDTH]; - uint16_t m_fontBuffer[CHRHEIGHT][CHRWIDTH]; + + uint16_t m_fontBkgBuffer[CHRHEIGHT][CHRWIDTH]; public: enum Colors {