163 lines
4.8 KiB
C++
163 lines
4.8 KiB
C++
#include <ili9341.h>
|
|
#include "stm32f4xx_hal.h"
|
|
#include "main.h"
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#define LCD_L 320
|
|
#define LCD_S 240
|
|
|
|
#define LCD_W LCD_L
|
|
#define LCD_H LCD_S
|
|
|
|
#define LCD_REG (*((volatile unsigned short *) 0x60000000)) /* DC = 0 */
|
|
#define LCD_RAM (*((volatile unsigned short *) 0x60080000)) /* DC = 1 */
|
|
|
|
|
|
Ili9341Fsmc::Ili9341Fsmc(volatile uint16_t *reg, volatile uint16_t *ram,
|
|
DMA_TypeDef *dma, uint32_t dmaStream,
|
|
bool horizontal)
|
|
: m_reg(reg ? reg : (volatile unsigned short *) 0x60000000)
|
|
, m_ram(ram ? ram : (volatile unsigned short *) 0x60080000)
|
|
, m_dma(dma)
|
|
, m_dmaStream(dmaStream)
|
|
, m_width(horizontal ? LCD_L : LCD_S)
|
|
, m_height(horizontal ? LCD_S : LCD_L)
|
|
, m_rectX(0)
|
|
, m_rectY(0)
|
|
, m_rectWidth(m_width)
|
|
, m_rectHeight(m_height)
|
|
{
|
|
LL_DMA_EnableIT_TC(m_dma, m_dmaStream);
|
|
LL_DMA_EnableIT_TE(m_dma, m_dmaStream);
|
|
|
|
WriteCmd(ILI9341_RESET);
|
|
HAL_Delay(10);
|
|
WriteCmd(ILI9341_DISPLAY_OFF);
|
|
WriteCmd(ILI9341_POWERA, {0x39, 0x2C, 0x00, 0x34, 0x02});
|
|
WriteCmd(ILI9341_POWERB, {0x00, 0xC1, 0x30});
|
|
WriteCmd(ILI9341_DTCA, {0x85, 0x00, 0x78});
|
|
WriteCmd(ILI9341_DTCB, {0x00, 0x00});
|
|
WriteCmd(ILI9341_POWER_SEQ, {0x64, 0x03, 0x12, 0x81});
|
|
WriteCmd(ILI9341_PRC, 0x20);
|
|
WriteCmd(ILI9341_POWER1, 0x23);
|
|
WriteCmd(ILI9341_POWER2, 0x10);
|
|
WriteCmd(ILI9341_VCOM1, {0x3E, 0x28});
|
|
WriteCmd(ILI9341_VCOM2, 0x86);
|
|
WriteCmd(ILI9341_MAC, horizontal ? 0xe8 : 0x48);
|
|
WriteCmd(ILI9341_PIXEL_FORMAT, 0x55);
|
|
WriteCmd(ILI9341_FRC, {0x00, 0x18});
|
|
WriteCmd(ILI9341_DFC, {0x08, 0x82, 0x27});
|
|
WriteCmd(ILI9341_3GAMMA_EN, 0x00);
|
|
WriteCmd(ILI9341_COLUMN_ADDR, {0x00, 0x00, (uint16_t)((m_width-1) >> 8), (uint16_t)((m_width-1) & 0x00ff)});
|
|
WriteCmd(ILI9341_PAGE_ADDR, {0x00, 0x00, (uint16_t)((m_height-1) >> 8), (uint16_t)((m_height-1) & 0x00ff)});
|
|
WriteCmd(ILI9341_GAMMA, 0x01);
|
|
WriteCmd(ILI9341_PGAMMA, {0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00});
|
|
WriteCmd(ILI9341_NGAMMA, {0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F});
|
|
WriteCmd(ILI9341_SLEEP_OUT);
|
|
HAL_Delay(100);
|
|
WriteCmd(ILI9341_DISPLAY_ON);
|
|
}
|
|
|
|
void Ili9341Fsmc::WriteCmd(uint16_t cmd, std::initializer_list<const uint16_t> params)
|
|
{
|
|
*m_reg = cmd;
|
|
for(uint16_t param : params)
|
|
*m_ram = param;
|
|
}
|
|
|
|
void Ili9341Fsmc::WriteCmd_(uint16_t cmd, uint16_t cnt, ...)
|
|
{
|
|
va_list argp;
|
|
va_start(argp, cnt);
|
|
|
|
*m_reg = cmd;
|
|
for(uint16_t n = 0; n < cnt; ++n) {
|
|
*m_ram = (uint16_t) va_arg(argp, uint32_t);
|
|
}
|
|
va_end(argp);
|
|
}
|
|
|
|
void Ili9341Fsmc::SetRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
|
|
{
|
|
if(x > m_width || y > m_height || !width || !height )
|
|
return;
|
|
|
|
WaitDmaIddle();
|
|
|
|
m_rectX = x;
|
|
m_rectY = y;
|
|
m_rectWidth = x + width > m_width ? m_width - x : width;
|
|
m_rectHeight = y + height > m_height ? m_height - x : height;
|
|
|
|
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)});
|
|
}
|
|
|
|
void Ili9341Fsmc::FillRect(uint16_t color)
|
|
{
|
|
uint32_t count = m_rectWidth * m_rectHeight;
|
|
WaitDmaIddle();
|
|
m_dmaColor = color;
|
|
WriteCmd(ILI9341_GRAM);
|
|
LL_DMA_SetM2MDstAddress(m_dma, m_dmaStream, (uint32_t)m_ram);
|
|
LL_DMA_SetM2MSrcAddress(m_dma, m_dmaStream, (uint32_t) &m_dmaColor);
|
|
LL_DMA_SetMemoryIncMode(m_dma, m_dmaStream, LL_DMA_MEMORY_NOINCREMENT);
|
|
LL_DMA_SetPeriphIncMode(m_dma, m_dmaStream, LL_DMA_PERIPH_NOINCREMENT);
|
|
SetupDmaSize(count);
|
|
m_dmaEngineBusy = true;
|
|
LL_DMA_EnableStream(m_dma, m_dmaStream);
|
|
|
|
// for(uint32_t pix = 0; pix < count; ++pix)
|
|
// *m_ram = color;
|
|
}
|
|
|
|
void Ili9341Fsmc::FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
|
|
{
|
|
SetRect(x, y, width, height);
|
|
FillRect(color);
|
|
}
|
|
|
|
void Ili9341Fsmc::SetupDmaSize(uint32_t size)
|
|
{
|
|
if(size > 0xffff) {
|
|
LL_DMA_SetDataLength(m_dma, m_dmaStream, 0xffff);
|
|
m_dmaRemainingPixels = size - 0xffff;
|
|
} else {
|
|
LL_DMA_SetDataLength(m_dma, m_dmaStream, size);
|
|
m_dmaRemainingPixels = 0;
|
|
}
|
|
}
|
|
|
|
void Ili9341Fsmc::DmaTransferComplete()
|
|
{
|
|
if(!m_dmaRemainingPixels)
|
|
m_dmaEngineBusy = false;
|
|
else {
|
|
SetupDmaSize(m_dmaRemainingPixels);
|
|
LL_DMA_EnableStream(m_dma, m_dmaStream);
|
|
}
|
|
}
|
|
|
|
void Ili9341Fsmc::Test()
|
|
{
|
|
FillRect(ILI9341_PINK);
|
|
WaitDmaIddle();
|
|
|
|
WriteCmd(ILI9341_GRAM);
|
|
uint16_t fillers[4] = { 0xf800, 0x7e0, 0x1f, 0xffff };
|
|
for(uint32_t y = 0; y < m_height; ++y) {
|
|
uint32_t x;
|
|
for(x = 0; x < m_width / 2; ++x) {
|
|
*m_ram = fillers[ (x&0x18) >> 3 ];
|
|
}
|
|
for( ; x < m_width; ++x) {
|
|
*m_ram = 0;
|
|
}
|
|
}
|
|
|
|
}
|