aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@embedded.pro>2017-02-18 16:32:57 +0100
committerJoel Bodenmann <joel@embedded.pro>2017-02-18 16:32:57 +0100
commitd3e995549655106a24d1089add89c1f674aa5d60 (patch)
tree0f398a7584d25136ba2aac3dfc1775d1dca20ec6 /drivers
parent8411fd1f036baa58d7b23253e64c3b0f016c2671 (diff)
downloaduGFX-d3e995549655106a24d1089add89c1f674aa5d60.tar.gz
uGFX-d3e995549655106a24d1089add89c1f674aa5d60.tar.bz2
uGFX-d3e995549655106a24d1089add89c1f674aa5d60.zip
Adding Altera Frame Reader IP Core display driver
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gdisp/AlteraFramereader/board_alteraframereader_template.h30
-rw-r--r--drivers/gdisp/AlteraFramereader/driver.mk2
-rw-r--r--drivers/gdisp/AlteraFramereader/gdisp_lld_alteraframereader.c280
-rw-r--r--drivers/gdisp/AlteraFramereader/gdisp_lld_config.h27
-rw-r--r--drivers/gdisp/AlteraFramereader/readme.txt27
5 files changed, 366 insertions, 0 deletions
diff --git a/drivers/gdisp/AlteraFramereader/board_alteraframereader_template.h b/drivers/gdisp/AlteraFramereader/board_alteraframereader_template.h
new file mode 100644
index 00000000..4fc7d071
--- /dev/null
+++ b/drivers/gdisp/AlteraFramereader/board_alteraframereader_template.h
@@ -0,0 +1,30 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#define SCREEN_WIDTH 800
+#define SCREEN_HEIGHT 480
+#define FRAMEREADER_BASE ALT_VIP_VFR_0_BASE
+
+#if GDISP_NEED_CONTROL
+ static void board_backlight(GDisplay* g, uint8_t percent)
+ {
+ (void)g;
+ (void)percent;
+ }
+
+ static void board_contrast(GDisplay* g, uint8_t percent)
+ {
+ (void)g;
+ (void)percent;
+ }
+
+ static void board_power(GDisplay* g, powermode_t pwr)
+ {
+ (void)g;
+ (void)pwr;
+ }
+#endif
diff --git a/drivers/gdisp/AlteraFramereader/driver.mk b/drivers/gdisp/AlteraFramereader/driver.mk
new file mode 100644
index 00000000..374cda11
--- /dev/null
+++ b/drivers/gdisp/AlteraFramereader/driver.mk
@@ -0,0 +1,2 @@
+GFXINC += $(GFXLIB)/drivers/gdisp/AlteraFramereader
+GFXSRC += $(GFXLIB)/drivers/gdisp/AlteraFramereader/gdisp_lld_alteraframereader.c
diff --git a/drivers/gdisp/AlteraFramereader/gdisp_lld_alteraframereader.c b/drivers/gdisp/AlteraFramereader/gdisp_lld_alteraframereader.c
new file mode 100644
index 00000000..5b27f944
--- /dev/null
+++ b/drivers/gdisp/AlteraFramereader/gdisp_lld_alteraframereader.c
@@ -0,0 +1,280 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#include <system.h>
+#include <io.h>
+#include <string.h>
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT GDISPVMT_alteraframereader
+#include "gdisp_lld_config.h"
+#include "../../../src/gdisp/gdisp_driver.h"
+#include "board_alteraframereader.h"
+
+#ifndef FRAMEREADER_BASE
+ #error "Framereader IP base address (FRAMEREADER_BASE) not set in board file."
+#endif
+#ifndef SCREEN_WIDTH
+ #error "Screen width (SCREEN_WIDTH) not set in board file."
+#endif
+#ifndef SCREEN_HEIGHT
+ #error "Screen height (SCREEN_HEIGHT) not set in board file."
+#endif
+
+// ToDo: Merge this into fbPriv
+typedef struct fbInfo {
+ void* pixels; // The pixel buffer
+ coord_t linelen; // The number of bytes per display line
+} fbInfo;
+
+typedef struct fbPriv {
+ fbInfo fbi; // Display information
+ void* frame0;
+ void* frame1;
+} fbPriv;
+
+/*===========================================================================*/
+/* Driver local routines . */
+/*===========================================================================*/
+
+#define PIXIL_POS(g, x, y) ((y) * ((fbPriv *)(g)->priv)->fbi.linelen + (x) * sizeof(LLDCOLOR_TYPE))
+#define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)(((char *)((fbPriv *)(g)->priv)->fbi.pixels)+pos))
+#define PRIV(g) ((fbPriv *)g->priv)
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay* g)
+{
+ // Allocate the frame buffers
+ PRIV(g)->frame0 = gfxAlloc(SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(LLDCOLOR_TYPE));
+ PRIV(g)->frame1 = gfxAlloc(SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(LLDCOLOR_TYPE));
+ if (!PRIV(g)->frame0 || !PRIV(g)->frame1) {
+ gfxHalt("Couldn't allocate memory for framebuffer\r\n");
+ }
+
+ // Initialize the private structure
+ g->g.Width = SCREEN_WIDTH;
+ g->g.Height = SCREEN_HEIGHT;
+ g->g.Backlight = 100;
+ g->g.Contrast = 50;
+ g->g.Orientation = GDISP_ROTATE_0;
+ g->g.Powermode = powerOn;
+ g->board = 0;
+ PRIV(g)->fbi.linelen = g->g.Width * sizeof(LLDCOLOR_TYPE); // bytes per line
+ PRIV(g)->fbi.pixels = PRIV(g)->frame0;
+
+ // Make sure the MSB is set so we bypass the data cache of the NIOS-II soft core
+ PRIV(g)->fbi.pixels = (void*)((char*)PRIV(g)->fbi.pixels + 0x80000000);
+
+ // Stop the framereader to allow for configuration
+ IOWR(ALT_VIP_VFR_0_BASE, 0x00, 0x00); // stop for config
+
+ // Frame 0
+ IOWR(ALT_VIP_VFR_0_BASE, 0x04, (uint32_t)PRIV(g)->frame0);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x05, SCREEN_WIDTH*SCREEN_HEIGHT/2);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x06, SCREEN_WIDTH*SCREEN_HEIGHT);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x08, SCREEN_WIDTH);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x09, SCREEN_HEIGHT);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x0a, 0x00);
+
+ // Frame 1
+ IOWR(ALT_VIP_VFR_0_BASE, 0x0b, (uint32_t)PRIV(g)->frame1);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x0c, SCREEN_WIDTH*SCREEN_HEIGHT/2);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x0d, SCREEN_WIDTH*SCREEN_HEIGHT);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x0f, SCREEN_WIDTH);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x10, SCREEN_HEIGHT);
+ IOWR(ALT_VIP_VFR_0_BASE, 0x11, 0x00);
+
+ // Select frame0 (user draws to frame0 -> double buffering disabled by default)
+ IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x00);
+
+ // Start the framebuffer reader
+ IOWR(ALT_VIP_VFR_0_BASE, 0x00, 0x01);
+
+ return TRUE;
+}
+
+LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g)
+{
+ unsigned pos;
+
+ #if GDISP_NEED_CONTROL
+ switch(g->g.Orientation) {
+ case GDISP_ROTATE_0:
+ default:
+ pos = PIXIL_POS(g, g->p.x, g->p.y);
+ break;
+ case GDISP_ROTATE_90:
+ pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1);
+ break;
+ case GDISP_ROTATE_180:
+ pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1);
+ break;
+ case GDISP_ROTATE_270:
+ pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x);
+ break;
+ }
+ #else
+ pos = PIXIL_POS(g, g->p.x, g->p.y);
+ #endif
+
+ PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
+}
+
+LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g)
+{
+ unsigned pos;
+ LLDCOLOR_TYPE color;
+
+ #if GDISP_NEED_CONTROL
+ switch(g->g.Orientation) {
+ case GDISP_ROTATE_0:
+ default:
+ pos = PIXIL_POS(g, g->p.x, g->p.y);
+ break;
+ case GDISP_ROTATE_90:
+ pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1);
+ break;
+ case GDISP_ROTATE_180:
+ pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1);
+ break;
+ case GDISP_ROTATE_270:
+ pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x);
+ break;
+ }
+ #else
+ pos = PIXIL_POS(g, g->p.x, g->p.y);
+ #endif
+
+ color = PIXEL_ADDR(g, pos)[0];
+ return gdispNative2Color(color);
+}
+
+#if GDISP_NEED_CONTROL
+ LLDSPEC void gdisp_lld_control(GDisplay* g)
+ {
+ switch(g->p.x) {
+ case GDISP_CONTROL_POWER:
+ if (g->g.Powermode == (powermode_t)g->p.ptr)
+ return;
+ switch((powermode_t)g->p.ptr) {
+ case powerOff: case powerOn: case powerSleep: case powerDeepSleep:
+ board_power(g, (powermode_t)g->p.ptr);
+ break;
+ default:
+ return;
+ }
+ g->g.Powermode = (powermode_t)g->p.ptr;
+ return;
+
+ case GDISP_CONTROL_ORIENTATION:
+ if (g->g.Orientation == (orientation_t)g->p.ptr)
+ return;
+ switch((orientation_t)g->p.ptr) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) {
+ coord_t tmp;
+
+ tmp = g->g.Width;
+ g->g.Width = g->g.Height;
+ g->g.Height = tmp;
+ }
+ break;
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ if (g->g.Orientation == GDISP_ROTATE_0 || g->g.Orientation == GDISP_ROTATE_180) {
+ coord_t tmp;
+
+ tmp = g->g.Width;
+ g->g.Width = g->g.Height;
+ g->g.Height = tmp;
+ }
+ break;
+ default:
+ return;
+ }
+ g->g.Orientation = (orientation_t)g->p.ptr;
+ return;
+
+ case GDISP_CONTROL_BACKLIGHT:
+ if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+ board_backlight(g, (unsigned)g->p.ptr);
+ g->g.Backlight = (unsigned)g->p.ptr;
+ return;
+
+ case GDISP_CONTROL_CONTRAST:
+ if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+ board_contrast(g, (unsigned)g->p.ptr);
+ g->g.Contrast = (unsigned)g->p.ptr;
+ return;
+
+ case GDISP_CONTROL_BUFFERS_SWAP:
+ if (PRIV(g)->fbi.pixels == PRIV(g)->frame0) {
+ PRIV(g)->fbi.pixels = PRIV(g)->frame1;
+ IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x00);
+ } else {
+ PRIV(g)->fbi.pixels = PRIV(g)->frame0;
+ IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x01);
+ }
+ return;
+
+ case GDISP_CONTROL_BUFFERS_ENABLE:
+ // Display frame0, draw to frame1
+ PRIV(g)->fbi.pixels = PRIV(g)->frame1;
+ IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x00);
+ return;
+
+ case GDISP_CONTROL_BUFFERS_DISABLE:
+ // Display frame0, draw to frame0
+ PRIV(g)->fbi.pixels = PRIV(g)->frame0;
+ IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x00);
+ return;
+ }
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS
+ LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
+ {
+ int i;
+ unsigned int addr;
+ int bytes_per_line;
+ int bytes_per_pixel;
+ uint8_t* line;
+
+ // Calculate some values required for further calculations
+ bytes_per_pixel = ((fbPriv*)g->priv)->fbi.linelen/g->g.Width; // must be 4
+ bytes_per_line = ((fbPriv*)g->priv)->fbi.linelen;
+
+ // Allocate line buffer
+ line = gfxAlloc(bytes_per_pixel * g->p.cx);
+
+ // Fill the line buffer with the solid color
+ for (i = 0; i < bytes_per_pixel * g->p.cx; i += 4) {
+ *((color_t*)(line + i)) = g->p.color;
+ }
+
+ // Calculate the address of the first pixel of the rectangle (top left corner)
+ addr = (int)((char *)((fbPriv *)g->priv)->fbi.pixels + (g->p.y * bytes_per_line) + (g->p.x * bytes_per_pixel));
+
+ // Copy filled line buffer to create rectangle
+ for (i = 0; i < g->p.cy; i++) {
+ memcpy((void*)addr, line, bytes_per_pixel * g->p.cx);
+ addr += bytes_per_line;
+ }
+
+ // Free the line buffer
+ gfxFree(line);
+ }
+#endif // GDISP_HARDWARE_FILLS
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/AlteraFramereader/gdisp_lld_config.h b/drivers/gdisp/AlteraFramereader/gdisp_lld_config.h
new file mode 100644
index 00000000..637f4f4e
--- /dev/null
+++ b/drivers/gdisp/AlteraFramereader/gdisp_lld_config.h
@@ -0,0 +1,27 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+#define GDISP_HARDWARE_DRAWPIXEL TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+
+#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+
+// gdispControl() options
+#define GDISP_CONTROL_BUFFERS_SWAP (GDISP_CONTROL_LLD+0) // Swap framebuffers (double buffering). Parameter is ignored.
+#define GDISP_CONTROL_BUFFERS_ENABLE (GDISP_CONTROL_LLD+1) // Enable double buffering. Parameter is ignored.
+#define GDISP_CONTROL_BUFFERS_DISABLE (GDISP_CONTROL_LLD+2) // Disable double buffering. Parameter is ignored.
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/drivers/gdisp/AlteraFramereader/readme.txt b/drivers/gdisp/AlteraFramereader/readme.txt
new file mode 100644
index 00000000..87777be4
--- /dev/null
+++ b/drivers/gdisp/AlteraFramereader/readme.txt
@@ -0,0 +1,27 @@
+This driver can be used for the "Frame Reader IP Core" that comes with the "Video and Image Processing Suite" package
+from Altera/Intel/Quartus.
+
+This driver takes advantage of the double buffering feature offered by the "Frame Reader IP Core". The following commands
+can be used through the gdispControl() API to manage the two frame buffers:
+
+ gdispControl(GDISP_CONTROL_BUFFERS_ENABLE, 0); // Enabel the two framebuffers (Disabled by default)
+ gdispControl(GDISP_CONTROL_BUFFERS_DISABLE, 0); // Disable the two framebuffers (Disabled by default)
+ gdispControl(GDISP_CONTROL_BUFFERS_SWAP, 0); // Swap the framebuffers (if enabled)
+
+The double buffering is taken care of completely by the driver. It sets the framebuffer pointers correctly so that it's
+transparent to the application. There's no need to handle the two framebuffers manually through the multiple displays
+support offered by uGFX. Using GDISP_CONTROL_BUFFERS_SWAP will swap the framebuffers on the actual hardware as well
+as swap the framebuffer pointers for the default GDisplay to draw to the other framebuffer.
+
+
+To use this driver:
+
+1. Add in your gfxconf.h:
+ a) #define GFX_USE_GDISP TRUE
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/gfx.mk
+ include $(GFXLIB)/drivers/gdisp/AlteraFramereader/driver.mk
+
+3. Add a board_alteraframereader.h to you project directory (or board directory)
+ base on one of the templates found in this drivers directory.