--- a/glcddrivers/Makefile +++ b/glcddrivers/Makefile @@ -63,6 +63,11 @@ LIBS += -lwiringPi endif +ifeq ($(HAVE_DRIVER_VUPLUS4K), 1) + DEFINES += -DHAVE_DRIVER_VUPLUS4K + OBJS += vuplus4k.o +endif + ### Implicit rules: %.o: %.c --- a/glcddrivers/drivers.c +++ b/glcddrivers/drivers.c @@ -50,6 +50,9 @@ #ifdef HAVE_DRIVER_ILI9341 #include "ili9341.h" #endif +#ifdef HAVE_DRIVER_VUPLUS4K +#include "vuplus4k.h" +#endif namespace GLCD { @@ -93,6 +96,9 @@ #endif #ifdef HAVE_DRIVER_ILI9341 {"ili9341", kDriverILI9341}, +#endif +#ifdef HAVE_DRIVER_VUPLUS4K + {"vuplus4k", kDriverVUPLUS4K}, #endif {"", kDriverUnknown} }; @@ -180,6 +186,10 @@ case kDriverILI9341: return new cDriverILI9341(config); #endif +#ifdef HAVE_DRIVER_VUPLUS4K + case kDriverVUPLUS4K: + return new cDriverVUPLUS4K(config); +#endif case kDriverUnknown: default: return NULL; --- a/glcddrivers/drivers.h +++ b/glcddrivers/drivers.h @@ -58,6 +58,9 @@ #endif kDriverUSBserLCD = 23, kDriverST7565RReel = 24, +#ifdef HAVE_DRIVER_VUPLUS4K + kDriverVUPLUS4K = 25, +#endif kDriverSerDisp = 100, kDriverG15daemon = 200 }; --- /dev/null +++ b/glcddrivers/vuplus4k.c @@ -0,0 +1,264 @@ +/* + * GraphLCD driver library + * + * vuplus4k.c - VUPLUS4K OLED driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * (c) redblue 2019 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "config.h" +#include "vuplus4k.h" + +namespace GLCD +{ + +cDriverVUPLUS4K::cDriverVUPLUS4K(cDriverConfig * config) +: cDriver(config), + fd(-1) +{ +} + +cDriverVUPLUS4K::~cDriverVUPLUS4K() +{ + DeInit(); +} + +int lcd_read_value(const char *filename) +{ + int value = 0; + FILE *fd = fopen(filename, "r"); + if (fd) { + int tmp; + if (fscanf(fd, "%x", &tmp) == 1) + value = tmp; + fclose(fd); + } + return value; +} + +int cDriverVUPLUS4K::Init() +{ + int x; + + width = config->width; + if (width <= 0) + width = lcd_read_value(XRES); + + height = config->height; + if (height <= 0) + height = lcd_read_value(YRES); + + bpp = lcd_read_value(BPP); + + switch (bpp) + { + case 8: + stride_bpp_value = 1; + break; + case 15: + case 16: + stride_bpp_value = 2; + break; + case 24: + case 32: + stride_bpp_value = 4; + break; + default: + stride_bpp_value = (bpp + 7) / 8; + } + + stride = width * stride_bpp_value; + + for (unsigned int i = 0; i < config->options.size(); i++) + { + if (config->options[i].name == "") + { + } + } + + if (config->device == "") + { + fd = open("/dev/dbox/lcd0", O_RDWR); + if (fd == -1) + fd = open("/dev/lcd0", O_RDWR); + if (fd == -1) + fd = open("/dev/dbox/oled0", O_RDWR); + if (fd == -1) + fd = open("/dev/oled0", O_RDWR); + } + else + { + fd = open(config->device.c_str(), O_RDWR); + } + + if (fd == -1) { + printf("cannot open lcd device\n"); + return -1; + } + + int tmp = LCD_MODE_BIN; + if (ioctl(fd, LCD_IOCTL_ASC_MODE, &tmp)) { + printf("failed to set lcd bin mode\n"); + } + + newLCD = new uint16_t[height * stride]; + if (newLCD) + memset(newLCD, 0, height * stride); + oldLCD = new uint16_t[height * stride]; + if (oldLCD) + memset(oldLCD, 0, height * stride); + + syslog(LOG_INFO, "%s: current lcd is %dx%d, %dbpp, vuplus4k lcd device was opened successfully\n", config->name.c_str(), width, height, bpp); + + *oldConfig = *config; + + // clear display + Clear(); + //Refresh(true); + + syslog(LOG_INFO, "%s: VUPLUS4K initialized.\n", config->name.c_str()); + return 0; +} + +int cDriverVUPLUS4K::DeInit() +{ + if (newLCD) + { + delete[] newLCD; + newLCD = 0; + } + if (oldLCD) + { + delete[] oldLCD; + oldLCD = 0; + } + if (-1 != fd) + { + close(fd); + fd=-1; + } + return 0; +} + +int cDriverVUPLUS4K::CheckSetup() +{ + if (config->width != oldConfig->width || + config->height != oldConfig->height) + { + DeInit(); + Init(); + return 0; + } + + if (config->upsideDown != oldConfig->upsideDown || + config->invert != oldConfig->invert) + { + oldConfig->upsideDown = config->upsideDown; + oldConfig->invert = config->invert; + return 1; + } + return 0; +} + +void cDriverVUPLUS4K::Clear() +{ + memset(newLCD, 0, width * height); +} + +void cDriverVUPLUS4K::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; + } + + uint32_t red, green, blue; + blue = (data & 0x000000FF) >> 0; + green = (data & 0x0000FF00) >> 8; + red = (data & 0x00FF0000) >> 16; + + unsigned char* row_pointers_bit_shift = (unsigned char*) &newLCD[0]; + int row_pointers_2_ptr = (y * width + x) * stride_bpp_value; + + if (config->invert) { + blue = 255 - blue; + green = 255 - green; + red = 255 - red; + } + + row_pointers_bit_shift[row_pointers_2_ptr+0]=blue; + row_pointers_bit_shift[row_pointers_2_ptr+1]=green; + row_pointers_bit_shift[row_pointers_2_ptr+2]=red; + row_pointers_bit_shift[row_pointers_2_ptr+3]=0xff; +} + +void cDriverVUPLUS4K::Refresh(bool refreshAll) +{ + int i; + char fileName[256]; + char str[32]; + FILE * fp; + unsigned char c; + + if (CheckSetup() > 0) + refreshAll = true; + + for (i = 0; i < height * stride; i++) + { + if (newLCD[i] != oldLCD[i]) + { + refreshAll = true; + break; + } + } + + if (refreshAll) + { + for (i = 0; i < height * stride; i++) + { + oldLCD[i] = newLCD[i]; + } + unsigned char* row_pointers_bit_shift = (unsigned char*) &newLCD[0]; + { + write(fd, row_pointers_bit_shift, height * stride); + } + } +} + +void cDriverVUPLUS4K::SetBrightness(unsigned int brightness) +{ + int value = 0; + value = 255 * brightness / 100; + + FILE *f = fopen("/proc/stb/lcd/oled_brightness", "w"); + if (!f) + f = fopen("/proc/stb/fp/oled_brightness", "w"); + if (f) + { + if (fprintf(f, "%d", value) == 0) + printf("write /proc/stb/lcd/oled_brightness failed!! (%m)\n"); + fclose(f); + } +} + +} // end of namespace --- /dev/null +++ b/glcddrivers/vuplus4k.h @@ -0,0 +1,64 @@ +/* + * GraphLCD driver library + * + * vuplus4k.c - VUPLUS4K OLED driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * (c) redblue + */ + + +#ifndef _GLCDDRIVERS_VUPLUS4K_H_ +#define _GLCDDRIVERS_VUPLUS4K_H_ + +#include "driver.h" + +namespace GLCD +{ + +#define XRES "/proc/stb/lcd/xres" +#define YRES "/proc/stb/lcd/yres" +#define BPP "/proc/stb/lcd/bpp" + +#ifndef LCD_IOCTL_ASC_MODE +#define LCDSET 0x1000 +#define LCD_IOCTL_ASC_MODE (21|LCDSET) +#define LCD_MODE_ASC 0 +#define LCD_MODE_BIN 1 +#endif + +#define FP_IOCTL_LCD_DIMM 3 + +class cDriverConfig; + +class cDriverVUPLUS4K : public cDriver +{ +private: + int fd; + uint16_t * newLCD; + uint16_t * oldLCD; + int bpp; + int stride; + int stride_bpp_value; + + int CheckSetup(); + +public: + cDriverVUPLUS4K(cDriverConfig * config); + virtual ~cDriverVUPLUS4K(); + + 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 --- a/Make.config +++ b/Make.config @@ -83,3 +83,6 @@ #HAVE_DRIVER_SSD1306=1 #HAVE_DRIVER_ILI9341=1 + +# uncomment this variable if you want to enable the experimental support for vuplus4k +HAVE_DRIVER_VUPLUS4K=1 --- a/README +++ b/README @@ -28,6 +28,7 @@ futaba md166 driver by Andreas Brachold usbserlcd driver by Manuel Reimer st7565r-reel driver by Georg Acher, BayCom GmbH based on simlcd.c by Carsten Siebholz, ported by Ufuk Altinkaynak + vuplus4k oled driver by redblue Project's homepage: https://projects.vdr-developer.org/projects/graphlcd-base GIT repo: https://projects.vdr-developer.org/git/graphlcd-base.git --- a/graphlcd.conf +++ b/graphlcd.conf @@ -117,6 +117,12 @@ ######################################################################## +[vuplus4k] +# Driver setting for the OLED VUPLUS4K +Driver=vuplus4k +#Width=480 +#Height=320 +# [ax206dpf] # THIS IS AN EXPERIMENTAL DRIVER! # You have to uncomment the variable HAVE_DRIVER_AX206DPF