diff options
-rw-r--r-- | Make.config | 2 | ||||
-rw-r--r-- | glcddrivers/Makefile | 8 | ||||
-rw-r--r-- | glcddrivers/drivers.c | 16 | ||||
-rw-r--r-- | glcddrivers/drivers.h | 9 | ||||
-rw-r--r-- | glcddrivers/ili9341.c | 366 | ||||
-rw-r--r-- | glcddrivers/ili9341.h | 53 | ||||
-rw-r--r-- | graphlcd.conf | 10 |
7 files changed, 457 insertions, 7 deletions
diff --git a/Make.config b/Make.config index 19cbfd8..3ddedd2 100644 --- a/Make.config +++ b/Make.config @@ -85,3 +85,5 @@ HAVE_DRIVER_VNCSERVER=1 #HAVE_DRIVER_picoLCD_256x64=1 #HAVE_DRIVER_SSD1306=1 + +#HAVE_DRIVER_ILI9341=1 diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile index dcf0c5f..e144698 100644 --- a/glcddrivers/Makefile +++ b/glcddrivers/Makefile @@ -40,7 +40,7 @@ ifeq ($(shell pkg-config --exists libusb && echo 1), 1) LIBS += $(shell pkg-config --libs libusb) DEFINES += -DHAVE_DRIVER_picoLCD_256x64 endif -endif +endif ifeq ($(HAVE_DRIVER_VNCSERVER), 1) ifeq ($(shell libvncserver-config --version >/dev/null && echo 1), 1) @@ -57,6 +57,12 @@ ifeq ($(HAVE_DRIVER_SSD1306), 1) LIBS += -lwiringPi endif +ifeq ($(HAVE_DRIVER_ILI9341), 1) + DEFINES += -DHAVE_DRIVER_ILI9341 + OBJS += ili9341.o + LIBS += -lwiringPi +endif + ### Implicit rules: %.o: %.c diff --git a/glcddrivers/drivers.c b/glcddrivers/drivers.c index 44e19c1..d30a2e5 100644 --- a/glcddrivers/drivers.c +++ b/glcddrivers/drivers.c @@ -42,6 +42,9 @@ #ifdef HAVE_DRIVER_SSD1306 #include "ssd1306.h" #endif +#ifdef HAVE_DRIVER_ILI9341 +#include "ili9341.h" +#endif namespace GLCD { @@ -68,16 +71,19 @@ tDriver drivers[] = {"g15daemon", kDriverG15daemon}, #ifdef HAVE_DRIVER_AX206DPF {"ax206dpf", kDriverAX206DPF}, -#endif +#endif #ifdef HAVE_DRIVER_picoLCD_256x64 {"picolcd256x64", kDriverPicoLCD_256x64}, -#endif +#endif #ifdef HAVE_DRIVER_VNCSERVER {"vncserver", kDriverVncServer}, -#endif +#endif #ifdef HAVE_DRIVER_SSD1306 {"ssd1306", kDriverSSD1306}, #endif +#ifdef HAVE_DRIVER_ILI9341 + {"ili9341", kDriverILI9341}, +#endif {"", kDriverUnknown} }; @@ -152,6 +158,10 @@ cDriver * CreateDriver(int driverID, cDriverConfig * config) case kDriverSSD1306: return new cDriverSSD1306(config); #endif +#ifdef HAVE_DRIVER_ILI9341 + case kDriverILI9341: + return new cDriverILI9341(config); +#endif case kDriverUnknown: default: return NULL; diff --git a/glcddrivers/drivers.h b/glcddrivers/drivers.h index f3bfbbf..fe19d2f 100644 --- a/glcddrivers/drivers.h +++ b/glcddrivers/drivers.h @@ -42,16 +42,19 @@ enum eDriver kDriverDM140GINK = 16, #ifdef HAVE_DRIVER_AX206DPF kDriverAX206DPF = 17, -#endif +#endif #ifdef HAVE_DRIVER_picoLCD_256x64 kDriverPicoLCD_256x64 = 18, -#endif +#endif #ifdef HAVE_DRIVER_VNCSERVER kDriverVncServer = 19, -#endif +#endif #ifdef HAVE_DRIVER_SSD1306 kDriverSSD1306 = 20, #endif +#ifdef HAVE_DRIVER_ILI9341 + kDriverILI9341 = 21, +#endif kDriverSerDisp = 100, kDriverG15daemon = 200 }; diff --git a/glcddrivers/ili9341.c b/glcddrivers/ili9341.c new file mode 100644 index 0000000..eb3a819 --- /dev/null +++ b/glcddrivers/ili9341.c @@ -0,0 +1,366 @@ +/* + * GraphLCD driver library + * + * ili9341.c - ILI9341 TFT driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * (c) 2015 Andreas Regel <andreas.regel AT powarman.de> + */ + +#include <stdint.h> +#include <syslog.h> +#include <unistd.h> +#include <cstring> + +#include <wiringPi.h> +#include <wiringPiSPI.h> + +#include "common.h" +#include "config.h" +#include "ili9341.h" + + +namespace GLCD +{ + +const int kLcdWidth = 240; +const int kLcdHeight = 320; + +const int kSpiBus = 0; + +const int kGpioReset = 4; +const int kGpioDC = 5; + +const uint8_t kCmdNop = 0x00; +const uint8_t kCmdSleepOut = 0x11; +const uint8_t kCmdGammaSet = 0x26; +const uint8_t kCmdDisplayOn = 0x29; +const uint8_t kCmdColumnAddressSet = 0x2A; +const uint8_t kCmdPageAddressSet = 0x2B; +const uint8_t kCmdMemoryWrite = 0x2C; +const uint8_t kCmdMemoryAccessControl = 0x36; +const uint8_t kCmdPixelFormatSet = 0x3A; +const uint8_t kCmdFrameRateControl = 0xB1; +const uint8_t kCmdDisplayFunctionControl = 0xB6; + +const uint8_t kCmdPowerControl1 = 0xC0; +const uint8_t kCmdPowerControl2 = 0xC1; +const uint8_t kCmdVcomControl1 = 0xC5; +const uint8_t kCmdVcomControl2 = 0xC7; +const uint8_t kCmdPositiveGammaControl = 0xE0; +const uint8_t kCmdNegativeGammaControl = 0xE1; + +const uint8_t kCmdPowerControlA = 0xCB; +const uint8_t kCmdPowerControlB = 0xCF; +const uint8_t kCmdDriverTimingControlA = 0xE8; +const uint8_t kCmdDriverTimingControlB = 0xEA; +const uint8_t kCmdPowerOnSequenceControl = 0xED; +const uint8_t kCmdUnknownEF = 0xEF; +const uint8_t kCmdEnable3G = 0xF2; +const uint8_t kCmdPumpRatioControl = 0xF7; + + +cDriverILI9341::cDriverILI9341(cDriverConfig * config) +: cDriver(config) +{ + refreshCounter = 0; + + wiringPiSetup(); +} + +cDriverILI9341::~cDriverILI9341() +{ +} + +int cDriverILI9341::Init() +{ + width = config->width; + if (width <= 0) + width = kLcdWidth; + height = config->height; + if (height <= 0) + height = kLcdHeight; + + for (unsigned int i = 0; i < config->options.size(); i++) + { + if (config->options[i].name == "") + { + } + } + + // setup lcd array (wanted state) + newLCD = new uint32_t[width * height]; + if (newLCD) + { + memset(newLCD, 0, width * height * sizeof(uint32_t)); + } + // setup lcd array (current state) + oldLCD = new uint32_t[width * height]; + if (oldLCD) + { + memset(oldLCD, 0, width * height * sizeof(uint32_t)); + } + + if (config->device == "") + { + return -1; + } + + pinMode(kGpioReset, OUTPUT); + pinMode(kGpioDC, OUTPUT); + + digitalWrite(kGpioReset, HIGH); + digitalWrite(kGpioDC, LOW); + + wiringPiSPISetup(kSpiBus, 64000000); + + /* reset display */ + Reset(); + + WriteCommand(kCmdUnknownEF); + WriteData(0x03); + WriteData(0x80); + WriteData(0x02); + WriteCommand(kCmdPowerControlB); + WriteData(0x00); + WriteData(0xC1); + WriteData(0x30); + WriteCommand(kCmdPowerOnSequenceControl); + WriteData(0x64); + WriteData(0x03); + WriteData(0x12); + WriteData(0x81); + WriteCommand(kCmdDriverTimingControlA); + WriteData(0x85); + WriteData(0x00); + WriteData(0x78); + WriteCommand(kCmdPowerControlA); + WriteData(0x39); + WriteData(0x2C); + WriteData(0x00); + WriteData(0x34); + WriteData(0x02); + WriteCommand(kCmdPumpRatioControl); + WriteData(0x20); + WriteCommand(kCmdDriverTimingControlB); + WriteData(0x00); + WriteData(0x00); + + WriteCommand(kCmdPowerControl1); + WriteData(0x23); + WriteCommand(kCmdPowerControl2); + WriteData(0x10); + WriteCommand(kCmdVcomControl1); + WriteData(0x3e); + WriteData(0x28); + WriteCommand(kCmdVcomControl2); + WriteData(0x86); + WriteCommand(kCmdMemoryAccessControl); + WriteData(0x48); + WriteCommand(kCmdPixelFormatSet); + WriteData(0x55); + WriteCommand(kCmdFrameRateControl); + WriteData(0x00); + WriteData(0x18); + WriteCommand(kCmdDisplayFunctionControl); + WriteData(0x08); + WriteData(0x82); + WriteData(0x27); + WriteCommand(kCmdEnable3G); + WriteData(0x00); + WriteCommand(kCmdGammaSet); + WriteData(0x01); + WriteCommand(kCmdPositiveGammaControl); + WriteData(0x0F); + WriteData(0x31); + WriteData(0x2B); + WriteData(0x0C); + WriteData(0x0E); + WriteData(0x08); + WriteData(0x4E); + WriteData(0xF1); + WriteData(0x37); + WriteData(0x07); + WriteData(0x10); + WriteData(0x03); + WriteData(0x0E); + WriteData(0x09); + WriteData(0x00); + WriteCommand(kCmdNegativeGammaControl); + WriteData(0x00); + WriteData(0x0E); + WriteData(0x14); + WriteData(0x03); + WriteData(0x11); + WriteData(0x07); + WriteData(0x31); + WriteData(0xC1); + WriteData(0x48); + WriteData(0x08); + WriteData(0x0F); + WriteData(0x0C); + WriteData(0x31); + WriteData(0x36); + WriteData(0x0F); + WriteCommand(kCmdSleepOut); + usleep(120000); + WriteCommand(kCmdDisplayOn); + + *oldConfig = *config; + + // clear display + Clear(); + + syslog(LOG_INFO, "%s: ILI9341 initialized.\n", config->name.c_str()); + return 0; +} + +int cDriverILI9341::DeInit() +{ + // free lcd array (wanted state) + if (newLCD) + { + delete[] newLCD; + } + // free lcd array (current state) + if (oldLCD) + { + delete[] oldLCD; + } + + return 0; +} + +int cDriverILI9341::CheckSetup() +{ + if (config->device != oldConfig->device || + config->width != oldConfig->width || + config->height != oldConfig->height) + { + DeInit(); + Init(); + return 0; + } + + if (config->upsideDown != oldConfig->upsideDown) + { + oldConfig->upsideDown = config->upsideDown; + return 1; + } + return 0; +} + +void cDriverILI9341::Clear() +{ + memset(newLCD, 0, width * height * sizeof(uint32_t)); +} + + +void cDriverILI9341::SetPixel(int x, int y, uint32_t data) +{ + if (x >= width || y >= height) + return; + + if (config->upsideDown) + { + x = width - 1 - x; + y = height - 1 - y; + } + + newLCD[y * width + x] = data; +} + + +void cDriverILI9341::Refresh(bool refreshAll) +{ + int y; + + if (CheckSetup() == 1) + refreshAll = true; + + if (config->refreshDisplay > 0) + { + refreshCounter = (refreshCounter + 1) % config->refreshDisplay; + if (!refreshAll && !refreshCounter) + refreshAll = true; + } + + refreshAll = true; + if (refreshAll) + { + SetWindow(0, 0, width - 1, height - 1); + WriteCommand(kCmdMemoryWrite); + for (y = 0; y < height; y++) + { + uint8_t line[width * 2]; + uint32_t * pixel = &newLCD[y * width]; + + for (int x = 0; x < (width * 2); x += 2) + { + line[x] = ((*pixel & 0x00F80000) >> 16) + | ((*pixel & 0x0000E000) >> 13); + line[x + 1] = ((*pixel & 0x00001C00) >> 5) + | ((*pixel & 0x000000F8) >> 3); + pixel++; + } + WriteData((uint8_t *) line, width * 2); + } + memcpy(oldLCD, newLCD, width * height * sizeof(uint32_t)); + // and reset RefreshCounter + refreshCounter = 0; + } + else + { + // draw only the changed bytes + } +} + +void cDriverILI9341::SetBrightness(unsigned int percent) +{ + //WriteCommand(kCmdSetContrast, percent * 255 / 100); +} + +void cDriverILI9341::Reset() +{ + digitalWrite(kGpioReset, HIGH); + usleep(100000); + digitalWrite(kGpioReset, LOW); + usleep(100000); + digitalWrite(kGpioReset, HIGH); + usleep(100000); +} + +void cDriverILI9341::SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) +{ + WriteCommand(kCmdColumnAddressSet); + WriteData(x0 >> 8); + WriteData(x0); + WriteData(x1 >> 8); + WriteData(x1); + WriteCommand(kCmdPageAddressSet); + WriteData(y0 >> 8); + WriteData(y0); + WriteData(y1 >> 8); + WriteData(y1); +} + +void cDriverILI9341::WriteCommand(uint8_t command) +{ + digitalWrite(kGpioDC, LOW); + wiringPiSPIDataRW(kSpiBus, &command, 1); + digitalWrite(kGpioDC, HIGH); +} + +void cDriverILI9341::WriteData(uint8_t data) +{ + wiringPiSPIDataRW(kSpiBus, &data, 1); +} + +void cDriverILI9341::WriteData(uint8_t * buffer, uint32_t length) +{ + wiringPiSPIDataRW(kSpiBus, buffer, length); +} + +} // end of namespace diff --git a/glcddrivers/ili9341.h b/glcddrivers/ili9341.h new file mode 100644 index 0000000..d729971 --- /dev/null +++ b/glcddrivers/ili9341.h @@ -0,0 +1,53 @@ +/* + * GraphLCD driver library + * + * ili9341.h - ILI9341 OLED driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * (c) 2015 Andreas Regel <andreas.regel AT powarman.de> + */ + +#ifndef _GLCDDRIVERS_ILI9341_H_ +#define _GLCDDRIVERS_ILI9341_H_ + +#include "driver.h" + +namespace GLCD +{ + +class cDriverConfig; + +class cDriverILI9341 : public cDriver +{ +private: + uint32_t * newLCD; // wanted state + uint32_t * oldLCD; // current state + int refreshCounter; + + int CheckSetup(); + + void Reset(); + void SetWindow(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1); + void WriteCommand(uint8_t command); + void WriteData(uint8_t data); + void WriteData(uint8_t * buffer, uint32_t length); + +public: + cDriverILI9341(cDriverConfig * config); + virtual ~cDriverILI9341(); + + virtual int Init(); + virtual int DeInit(); + + virtual void Clear(); + virtual void SetPixel(int x, int y, uint32_t data); + //virtual void Set8Pixels(int x, int y, unsigned char data); + virtual void Refresh(bool refreshAll = false); + virtual void SetBrightness(unsigned int percent); +}; + +} // end of namespace + +#endif diff --git a/graphlcd.conf b/graphlcd.conf index 66ee396..fce9270 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -672,3 +672,13 @@ Driver=ssd1306 Device=0 Width=128 Height=64 + +[ili9341] +# ili9341 driver +# This is a driver module for the ILI9341 TFT display controller. +# Default size: 320x240 +Driver=ili9341 +Device=0 +Width=320 +Height=240 + |