#include #include "stm32f4xx_hal.h" #include "main.h" #include #include #include #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 */ #define ILI9341_NOP 0x00 #define ILI9341_RESET 0x01 #define ILI9341_READ_DISPLAY_IDENTIFICATION_INFORMATION 0x04 #define ILI9341_READ_DISPLAY_STATUS 0x09 #define ILI9341_READ_DISPLAY_POWER_MODE 0x0A #define ILI9341_READ_DISPLAY_MADCTL 0x0B #define ILI9341_READ_DISPLAY_PIXEL_FORMAT 0x0C #define ILI9341_READ_DISPLAY_IMAGE_FORMAT 0x0D #define ILI9341_READ_DISPLAY_SIGNAL_MODE 0x0E #define ILI9341_READ_DISPLAY_SELF_DIAGNOSTIC_RESULT 0x0F #define ILI9341_ENTER_SLEEP_MODE 0x10 #define ILI9341_SLEEP_OUT 0x11 #define ILI9341_PARTIAL_MODE_ON 0x12 #define ILI9341_NORMAL_DISPLAY_MODE_ON 0x13 #define ILI9341_DISPLAY_INVERSION_OFF 0x20 #define ILI9341_DISPLAY_INVERSION_ON 0x21 #define ILI9341_GAMMA 0x26 #define ILI9341_DISPLAY_OFF 0x28 #define ILI9341_DISPLAY_ON 0x29 #define ILI9341_COLUMN_ADDR 0x2A #define ILI9341_PAGE_ADDR 0x2B #define ILI9341_GRAM 0x2C #define ILI9341_COLOR_SET 0x2D #define ILI9341_MEMORY_READ 0x2E #define ILI9341_PARTIAL_AREA 0x30 #define ILI9341_VERTICAL_SCROLLING_DEFINITION 0x33 #define ILI9341_TEARING_EFFECT_LINE_OFF 0x34 #define ILI9341_TEARING_EFFECT_LINE_ON 0x35 #define ILI9341_MAC 0x36 #define ILI9341_VERTICAL_SCROLLING_START_ADDRESS 0x37 #define ILI9341_IDLE_MODE_OFF 0x38 #define ILI9341_IDLE_MODE_ON 0x39 #define ILI9341_PIXEL_FORMAT 0x3A #define ILI9341_WMC 0x3C #define ILI9341_RMC 0x3E #define ILI9341_SET_TEAR_SCANLINE 0x44 #define ILI9341_WDB 0x51 #define ILI9341_READ_DISPLAY_BRIGHTNESS 0x52 #define ILI9341_WCD 0x53 #define ILI9341_READ_CTRL_DISPLAY 0x54 #define ILI9341_WCABC 0x55 #define ILI9341_RCABC 0x56 #define ILI9341_WCABCMB 0x5E #define ILI9341_RCABCMB 0x5F #define ILI9341_RGB_INTERFACE 0xB0 #define ILI9341_FRC 0xB1 #define ILI9341_FRAME_CTRL_NM 0xB2 #define ILI9341_FRAME_CTRL_IM 0xB3 #define ILI9341_FRAME_CTRL_PM 0xB4 #define ILI9341_BPC 0xB5 #define ILI9341_DFC 0xB6 #define ILI9341_ENTRY_MODE_SET 0xB7 #define ILI9341_BACKLIGHT_CONTROL_1 0xB8 #define ILI9341_BACKLIGHT_CONTROL_2 0xB9 #define ILI9341_BACKLIGHT_CONTROL_3 0xBA #define ILI9341_BACKLIGHT_CONTROL_4 0xBB #define ILI9341_BACKLIGHT_CONTROL_5 0xBC #define ILI9341_BACKLIGHT_CONTROL_6 0xBD #define ILI9341_BACKLIGHT_CONTROL_7 0xBE #define ILI9341_BACKLIGHT_CONTROL_8 0xBF #define ILI9341_POWER1 0xC0 #define ILI9341_POWER2 0xC1 #define ILI9341_VCOM1 0xC5 #define ILI9341_VCOM2 0xC7 #define ILI9341_POWERA 0xCB #define ILI9341_POWERB 0xCF #define ILI9341_READ_ID1 0xDA #define ILI9341_READ_ID2 0xDB #define ILI9341_READ_ID3 0xDC #define ILI9341_PGAMMA 0xE0 #define ILI9341_NGAMMA 0xE1 #define ILI9341_DTCA 0xE8 #define ILI9341_DTCB 0xEA #define ILI9341_POWER_SEQ 0xED #define ILI9341_3GAMMA_EN 0xF2 #define ILI9341_INTERFACE 0xF6 #define ILI9341_PRC 0xF7 // Color definitions #define ILI9341_BLACK 0x0000 /* 0, 0, 0 */ #define ILI9341_NAVY 0x000F /* 0, 0, 128 */ #define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */ #define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */ #define ILI9341_MAROON 0x7800 /* 128, 0, 0 */ #define ILI9341_PURPLE 0x780F /* 128, 0, 128 */ #define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */ #define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */ #define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */ #define ILI9341_BLUE 0x001F /* 0, 0, 255 */ #define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */ #define ILI9341_CYAN 0x07FF /* 0, 255, 255 */ #define ILI9341_RED 0xF800 /* 255, 0, 0 */ #define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */ #define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */ #define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */ #define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */ #define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ #define ILI9341_PINK 0xF81F Ili9341Fsmc::Ili9341Fsmc(volatile uint16_t *reg, volatile uint16_t *ram, DMA_TypeDef *dma, uint32_t dmaStream, bool horizontal) : m_reg(reg) , m_ram(ram) , 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 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; } } }