/* * 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 #include #include #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 typedef struct fbPriv { void* pixels; // The pixel buffer coord_t linelen; // The number of bytes per display line void* frame0; void* frame1; } fbPriv; /*===========================================================================*/ /* Driver local routines . */ /*===========================================================================*/ #define PIXIL_POS(g, x, y) ((y) * ((fbPriv *)(g)->priv)->linelen + (x) * sizeof(LLDCOLOR_TYPE)) #define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)(((char *)((fbPriv *)(g)->priv)->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)->linelen = g->g.Width * sizeof(LLDCOLOR_TYPE); // bytes per line PRIV(g)->pixels = PRIV(g)->frame0; // Make sure the MSB is set so we bypass the data cache of the NIOS-II soft core PRIV(g)->pixels = (void*)((char*)PRIV(g)->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)->pixels == PRIV(g)->frame0) { PRIV(g)->pixels = PRIV(g)->frame1; IOWR(ALT_VIP_VFR_0_BASE, 0x03, 0x00); } else { PRIV(g)->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)->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)->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)->linelen/g->g.Width; // must be 4 bytes_per_line = ((fbPriv*)g->priv)->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)->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 */