SSD1289 streaming driver (untested)

X streaming driver (untested)
Nokia6610 fixes
Read pixel streaming support for low level driver.
ugfx_release_2.6
inmarket 2013-09-30 00:05:07 +10:00
parent a2aa837e09
commit 6499da5be3
12 changed files with 432 additions and 619 deletions

View File

@ -107,7 +107,7 @@
/* Driver local variables. */
/*===========================================================================*/
#if GDISP_HARDWARE_STREAM
#if GDISP_HARDWARE_STREAM_WRITE
static color_t savecolor;
#if GDISP_GE8_BROKEN_CONTROLLER
static color_t firstcolor;
@ -184,18 +184,15 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
return TRUE;
}
#if GDISP_HARDWARE_STREAM
LLDSPEC void gdisp_lld_stream_start(GDISPDriver *g) {
#if GDISP_HARDWARE_STREAM_WRITE
LLDSPEC void gdisp_lld_write_start(GDISPDriver *g) {
acquire_bus();
write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1); // Column address set
write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1); // Page address set
write_cmd(RAMWR);
g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
}
#endif
#if GDISP_HARDWARE_STREAM
LLDSPEC void gdisp_lld_stream_color(GDISPDriver *g) {
LLDSPEC void gdisp_lld_write_color(GDISPDriver *g) {
#if GDISP_GE8_BROKEN_CONTROLLER
if (!(g->flags & GDISP_FLG_RUNBYTE)) {
firstcolor = g->p.color;
@ -211,10 +208,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
g->flags |= GDISP_FLG_ODDBYTE;
}
}
#endif
#if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_STOP
LLDSPEC void gdisp_lld_stream_stop(GDISPDriver *g) {
LLDSPEC void gdisp_lld_write_stop(GDISPDriver *g) {
if ((g->flags & GDISP_FLG_ODDBYTE)) {
#if GDISP_GE8_BROKEN_CONTROLLER
/**
@ -247,7 +241,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
#endif
#if GDISP_HARDWARE_DRAWPIXEL
void gdisp_lld_draw_pixel(GDISPDriver *g) {
LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
acquire_bus();
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
@ -275,7 +269,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
/* ---- Optional Routines ---- */
#if GDISP_HARDWARE_FILLS
void gdisp_lld_fill_area(GDISPDriver *g) {
LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
unsigned tuples;
tuples = (g->p.cx*g->p.cy+1)>>1; // With an odd sized area we over-print by one pixel.
@ -308,7 +302,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
#endif
#if GDISP_HARDWARE_BITFILLS
void gdisp_lld_blit_area(GDISPDriver *g) {
LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
coord_t lg, x, y;
color_t c1, c2;
unsigned tuples;

View File

@ -25,7 +25,9 @@
#define GDISP_DRIVER_NAME "Nokia6610GE8"
#define GDISP_DRIVER_STRUCT GDISP_Nokia6610GE8
#define GDISP_NOKIA_ORIENTATION TRUE
#ifndef GDISP_NOKIA_ORIENTATION
#define GDISP_NOKIA_ORIENTATION TRUE
#endif
#if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
#define GDISP_HARDWARE_CONTROL TRUE
@ -34,8 +36,7 @@
#define GDISP_HARDWARE_BITFILLS TRUE
#else
#define GDISP_HARDWARE_CONTROL TRUE
#define GDISP_HARDWARE_STREAM TRUE
#define GDISP_HARDWARE_STREAM_STOP TRUE
#define GDISP_HARDWARE_STREAM_WRITE TRUE
#endif
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB444

View File

@ -17,8 +17,8 @@
#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
/* Include the emulation code for things we don't support */
#include "gdisp/lld/emulation.c"
#define GDISP_LLD_DECLARATIONS
#include "gdisp/lld/gdisp_lld.h"
/*===========================================================================*/
/* Driver local definitions. */
@ -52,7 +52,7 @@ static inline void set_cursor(coord_t x, coord_t y) {
* Reg 0x004F is 9 bit
* Use a bit mask to make sure they are not set too high
*/
switch(GDISP.Orientation) {
switch(g->g.Orientation) {
case GDISP_ROTATE_180:
write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-x) & 0x00FF);
write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-y) & 0x01FF);
@ -85,14 +85,14 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
* 0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
*/
switch(GDISP.Orientation) {
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (x & 0x00FF));
write_reg(0x45, y & 0x01FF);
write_reg(0x46, (y+cy-1) & 0x01FF);
break;
case GDISP_ROTATE_270:
write_reg(0x44, (((y+cy-1) << 8) & 0xFF00 ) | (y & 0x00FF));
write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
write_reg(0x45, x & 0x01FF);
write_reg(0x46, (x+cx-1) & 0x01FF);
break;
@ -112,7 +112,7 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
}
static inline void reset_viewport(void) {
set_viewport(0, 0, GDISP.Width, GDISP.Height);
set_viewport(0, 0, g->g.Width, g->g.Height);
}
/*===========================================================================*/
@ -123,18 +123,7 @@ static inline void reset_viewport(void) {
/* Driver exported functions. */
/*===========================================================================*/
/* ---- Required Routines ---- */
/*
The following 2 routines are required.
All other routines are optional.
*/
/**
* @brief Low level GDISP driver initialization.
*
* @notapi
*/
bool_t gdisp_lld_init(void) {
LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
/* Initialise your display */
init_board();
@ -196,365 +185,103 @@ bool_t gdisp_lld_init(void) {
set_backlight(GDISP_INITIAL_BACKLIGHT);
/* Initialise the GDISP structure */
GDISP.Width = GDISP_SCREEN_WIDTH;
GDISP.Height = GDISP_SCREEN_HEIGHT;
GDISP.Orientation = GDISP_ROTATE_0;
GDISP.Powermode = powerOn;
GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
GDISP.Contrast = GDISP_INITIAL_CONTRAST;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
GDISP.clipx0 = 0;
GDISP.clipy0 = 0;
GDISP.clipx1 = GDISP.Width;
GDISP.clipy1 = GDISP.Height;
#endif
g->g.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
g->g.Contrast = GDISP_INITIAL_CONTRAST;
return TRUE;
}
/**
* @brief Draws a pixel on the display.
*
* @param[in] x X location of the pixel
* @param[in] y Y location of the pixel
* @param[in] color The color of the pixel
*
* @notapi
*/
void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
#endif
acquire_bus();
set_cursor(x, y);
write_reg(0x0022, color);
release_bus();
}
/* ---- Optional Routines ---- */
/*
All the below routines are optional.
Defining them will increase speed but everything
will work if they are not defined.
If you are not using a routine - turn it off using
the appropriate GDISP_HARDWARE_XXXX macro.
Don't bother coding for obvious similar routines if
there is no performance penalty as the emulation software
makes a good job of using similar routines.
eg. If gfillarea() is defined there is little
point in defining clear() unless the
performance bonus is significant.
For good performance it is suggested to implement
fillarea() and blitarea().
*/
#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
/**
* @brief Clear the display.
* @note Optional - The high level driver can emulate using software.
*
* @param[in] color The color of the pixel
*
* @notapi
*/
void gdisp_lld_clear(color_t color) {
unsigned area;
area = GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT;
#if GDISP_HARDWARE_STREAM_WRITE
LLDSPEC void gdisp_lld_write_start(GDISPDriver *g) {
acquire_bus();
reset_viewport();
set_cursor(0, 0);
set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
stream_start();
#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
uint8_t i;
dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
for (i = area/65535; i; i--) {
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
}
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
#else
uint32_t index;
for(index = 0; index < area; index++)
write_data(color);
#endif //#ifdef GDISP_USE_DMA
}
LLDSPEC void gdisp_lld_write_color(GDISPDriver *g) {
write_data(color);
}
LLDSPEC void gdisp_lld_write_stop(GDISPDriver *g) {
stream_stop();
release_bus();
}
#endif
#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
/**
* @brief Fill an area with a color.
* @note Optional - The high level driver can emulate using software.
*
* @param[in] x, y The start filled area
* @param[in] cx, cy The width and height to be filled
* @param[in] color The color of the fill
*
* @notapi
*/
void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
unsigned area;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
#endif
area = cx*cy;
#if GDISP_HARDWARE_STREAM_READ
LLDSPEC void gdisp_lld_read_start(GDISPDriver *g) {
uint16_t dummy;
acquire_bus();
set_viewport(x, y, cx, cy);
set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
stream_start();
#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
uint8_t i;
dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
for (i = area/65535; i; i--) {
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
}
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
#else
uint32_t index;
for(index = 0; index < area; index++)
write_data(color);
#endif //#ifdef GDISP_USE_DMA
setreadmode();
dummy = read_data(); // dummy read
}
LLDSPEC color_t gdisp_lld_read_color(GDISPDriver *g) {
return read_data();
}
LLDSPEC void gdisp_lld_read_stop(GDISPDriver *g) {
setwritemode();
stream_stop();
release_bus();
}
#endif
#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
/**
* @brief Fill an area with a bitmap.
* @note Optional - The high level driver can emulate using software.
*
* @param[in] x, y The start filled area
* @param[in] cx, cy The width and height to be filled
* @param[in] srcx, srcy The bitmap position to start the fill from
* @param[in] srccx The width of a line in the bitmap.
* @param[in] buffer The pixels to use to fill the area.
*
* @notapi
*/
void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
if (srcx+cx > srccx) cx = srccx - srcx;
if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
#endif
buffer += srcx + srcy * srccx;
#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
acquire_bus();
set_viewport(x, y, cx, cy);
set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
stream_start();
#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
uint32_t area = cx*cy;
uint8_t i;
dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
for (i = area/65535; i; i--) {
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
}
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
#else
coord_t endx, endy;
uint32_t lg;
endx = srcx + cx;
endy = y + cy;
lg = srccx - cx;
for(; y < endy; y++, buffer += lg)
for(x=srcx; x < endx; x++)
write_data(*buffer++);
#endif //#ifdef GDISP_USE_DMA
dma_with_noinc(&color, g->p.cx*g->p.cy)
stream_stop();
release_bus();
}
#endif
#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
/**
* @brief Get the color of a particular pixel.
* @note Optional.
* @note If x,y is off the screen, the result is undefined.
*
* @param[in] x, y The pixel to be read
*
* @notapi
*/
color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
color_t color;
#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
pixel_t *buffer;
coord_t ycnt;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
#endif
buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
acquire_bus();
set_cursor(x, y);
set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
stream_start();
/* FSMC timing */
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0 ;
color = read_data(); // dummy read
color = read_data();
/* FSMC timing */
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
stream_stop();
release_bus();
return color;
}
#endif
#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
/**
* @brief Scroll vertically a section of the screen.
* @note Optional.
* @note If x,y + cx,cy is off the screen, the result is undefined.
* @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
*
* @param[in] x, y The start of the area to be scrolled
* @param[in] cx, cy The size of the area to be scrolled
* @param[in] lines The number of lines to scroll (Can be positive or negative)
* @param[in] bgcolor The color to fill the newly exposed area.
*
* @notapi
*/
void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
coord_t row0, row1;
unsigned i, gap, abslines, j;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
#endif
abslines = lines < 0 ? -lines : lines;
acquire_bus();
if ((coord_t)abslines >= cy) {
abslines = cy;
gap = 0;
if (g->p.x2 == g->p.cx) {
dma_with_inc(buffer, g->p.cx*g->p.cy);
} else {
gap = cy - abslines;
for(i = 0; i < gap; i++) {
if(lines > 0) {
row0 = y + i + lines;
row1 = y + i;
} else {
row0 = (y - i - 1) + lines;
row1 = (y - i - 1);
}
/* read row0 into the buffer and then write at row1*/
set_viewport(x, row0, cx, 1);
stream_start();
/* FSMC timing */
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0 ;
j = read_data(); // dummy read
for (j = 0; (coord_t)j < cx; j++)
buf[j] = read_data();
/* FSMC timing */
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
stream_stop();
set_viewport(x, row1, cx, 1);
stream_start();
for (j = 0; (coord_t)j < cx; j++)
write_data(buf[j]);
stream_stop();
}
for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
dma_with_inc(buffer, g->p.cy);
}
/* fill the remaining gap */
set_viewport(x, lines > 0 ? (y+(coord_t)gap) : y, cx, abslines);
stream_start();
gap = cx*abslines;
for(i = 0; i < gap; i++) write_data(bgcolor);
stream_stop();
release_bus();
}
#endif
#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
/**
* @brief Driver Control
* @details Unsupported control codes are ignored.
* @note The value parameter should always be typecast to (void *).
* @note There are some predefined and some specific to the low level driver.
* @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
* GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
* GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
* that only supports off/on anything other
* than zero is on.
* GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
* GDISP_CONTROL_LLD - Low level driver control constants start at
* this value.
*
* @param[in] what What to do.
* @param[in] value The value to use (always cast to a void *).
*
* @notapi
*/
void gdisp_lld_control(unsigned what, void *value) {
switch(what) {
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
switch(g->p.x) {
case GDISP_CONTROL_POWER:
if (GDISP.Powermode == (gdisp_powermode_t)value)
if (g->g.Powermode == (powermode_t)g->p.ptr)
return;
switch((gdisp_powermode_t)value) {
switch((powermode_t)g->p.ptr) {
case powerOff:
acquire_bus();
write_reg(0x0010, 0x0000); // leave sleep mode
write_reg(0x0007, 0x0000); // halt operation
write_reg(0x0000, 0x0000); // turn off oszillator
write_reg(0x0010, 0x0001); // enter sleepmode
write_reg(0x0000, 0x0000); // turn off oscillator
write_reg(0x0010, 0x0001); // enter sleep mode
release_bus();
break;
case powerOn:
acquire_bus();
write_reg(0x0010, 0x0000); // leave sleep mode
release_bus();
if (GDISP.Powermode != powerSleep)
if (g->g.Powermode != powerSleep)
gdisp_lld_init();
break;
case powerSleep:
@ -565,20 +292,20 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
default:
return;
}
GDISP.Powermode = (gdisp_powermode_t)value;
g->g.Powermode = (powermode_t)g->p.ptr;
return;
case GDISP_CONTROL_ORIENTATION:
if (GDISP.Orientation == (gdisp_orientation_t)value)
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
switch((gdisp_orientation_t)value) {
switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0:
acquire_bus();
write_reg(0x0001, 0x2B3F);
/* ID = 11 AM = 0 */
write_reg(0x0011, 0x6070);
release_bus();
GDISP.Height = GDISP_SCREEN_HEIGHT;
GDISP.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
break;
case GDISP_ROTATE_90:
acquire_bus();
@ -586,8 +313,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
/* ID = 11 AM = 1 */
write_reg(0x0011, 0x6078);
release_bus();
GDISP.Height = GDISP_SCREEN_WIDTH;
GDISP.Width = GDISP_SCREEN_HEIGHT;
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
break;
case GDISP_ROTATE_180:
acquire_bus();
@ -595,8 +322,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
/* ID = 01 AM = 0 */
write_reg(0x0011, 0x6040);
release_bus();
GDISP.Height = GDISP_SCREEN_HEIGHT;
GDISP.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
break;
case GDISP_ROTATE_270:
acquire_bus();
@ -604,31 +331,23 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
/* ID = 01 AM = 1 */
write_reg(0x0011, 0x6048);
release_bus();
GDISP.Height = GDISP_SCREEN_WIDTH;
GDISP.Width = GDISP_SCREEN_HEIGHT;
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
break;
default:
return;
}
#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
GDISP.clipx0 = 0;
GDISP.clipy0 = 0;
GDISP.clipx1 = GDISP.Width;
GDISP.clipy1 = GDISP.Height;
#endif
GDISP.Orientation = (gdisp_orientation_t)value;
g->g.Orientation = (orientation_t)value;
return;
case GDISP_CONTROL_BACKLIGHT:
if ((unsigned)value > 100)
value = (void *)100;
set_backlight((unsigned)value);
GDISP.Backlight = (unsigned)value;
if ((unsigned)g->p.ptr > 100)
g->p.ptr = (void *)100;
set_backlight((unsigned)g->p.ptr);
g->g.Backlight = (unsigned)g->p.ptr;
return;
//case GDISP_CONTROL_CONTRAST:
default:
return;
/*
case GDISP_CONTROL_CONTRAST:
*/
}
}
#endif

View File

@ -112,7 +112,28 @@ static inline void write_data(uint16_t data) {
CLR_WR; SET_WR;
}
#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
/**
* @brief Set the bus in read mode
*
* @notapi
*/
static inline void setreadmode(void) {
// change pin mode to digital input
palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
CLR_RD;
}
/**
* @brief Set the bus back into write mode
*
* @notapi
*/
static inline void setwritemode(void) {
// change pin mode back to digital output
SET_RD;
palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
}
/**
* @brief Read data from the lcd.
*
@ -123,22 +144,13 @@ static inline void write_data(uint16_t data) {
* @notapi
*/
static inline uint16_t read_data(void) {
uint16_t value;
// change pin mode to digital input
palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
CLR_RD;
value = palReadPort(GPIOE);
value = palReadPort(GPIOE);
SET_RD;
// change pin mode back to digital output
palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
return value;
return palReadPort(GPIOE);
}
#endif
#if defined(GDISP_USE_DMA)
#error "GDISP - SSD1289: The GPIO interface does not support DMA"
#endif
#endif /* _GDISP_LLD_BOARD_H */
/** @} */

View File

@ -18,10 +18,7 @@
#define GDISP_REG ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
#define GDISP_RAM ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
#define GDISP_USE_FSMC
#define GDISP_USE_DMA
#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
const unsigned char FSMC_Bank = 0;
@ -55,20 +52,22 @@ static inline void init_board(void) {
/* FSMC setup for F1/F3 */
rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
#error "DMA not implemented for F1/F3 Devices"
#if defined(GDISP_USE_DMA)
#error "GDISP: SSD1289 - DMA not implemented for F1/F3 Devices"
#endif
#elif defined(STM32F4XX) || defined(STM32F2XX)
/* STM32F2-F4 FSMC init */
rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
#if defined(GDISP_USE_DMA)
if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
#else
#warning "GDISP: SSD1289 - DMA is supported for F2/F4 Devices. Define GDISP_USE_DMA in your gfxconf.h to turn this on for better performance."
#endif
#else
#error "FSMC not implemented for this device"
#error "GDISP: SSD1289 - FSMC not implemented for this device"
#endif
/* set pins to FSMC mode */
@ -155,17 +154,61 @@ static inline void write_index(uint16_t index) { GDISP_REG = index; }
*/
static inline void write_data(uint16_t data) { GDISP_RAM = data; }
#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
/**
* @brief Set the bus in read mode
*
* @notapi
*/
static inline void setreadmode(void) {
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0; /* FSMC timing */
}
/**
* @brief Set the bus back into write mode
*
* @notapi
*/
static inline void setwritemode(void) {
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0; /* FSMC timing */
}
/**
* @brief Read data from the lcd.
*
* @return The data from the lcd
* @note The chip select may need to be asserted/de-asserted
* around the actual spi read
*
*
* @notapi
*/
static inline uint16_t read_data(void) { return GDISP_RAM; }
#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
/**
* @brief Transfer data using DMA but don't increment the source address
*/
static inline dma_with_noinc(color_t *buffer, int area) {
dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
for (; area > 0; area -= 65535) {
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
}
}
/**
* @brief Transfer data using DMA incrementing the source address
*/
static inline dma_with_inc(color_t *buffer, int area) {
dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
for (; area > 0; area -= 65535) {
dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
dmaStreamEnable(GDISP_DMA_STREAM);
dmaWaitCompletion(GDISP_DMA_STREAM);
}
}
#endif
#endif /* _GDISP_LLD_BOARD_H */

View File

@ -87,7 +87,24 @@ static inline void write_data(uint16_t data) {
}
#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
/**
* @brief Set the bus in read mode
*
* @notapi
*/
static inline void setreadmode(void) {
}
/**
* @brief Set the bus back into write mode
*
* @notapi
*/
static inline void setwritemode(void) {
}
/**
* @brief Read data from the lcd.
*
@ -100,6 +117,24 @@ static inline void write_data(uint16_t data) {
static inline uint16_t read_data(void) {
}
/**
* The below section you can replace with #error if your interface doesn't support DMA
*/
#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
//#error "GDISP - SSD1289: This interface does not support DMA"
/**
* @brief Transfer data using DMA but don't increment the source address
*/
static inline dma_with_noinc(color_t *buffer, int area) {
}
/**
* @brief Transfer data using DMA incrementing the source address
*/
static inline dma_with_inc(color_t *buffer, int area) {
}
#endif
#endif /* _GDISP_LLD_BOARD_H */

View File

@ -23,13 +23,16 @@
/*===========================================================================*/
#define GDISP_DRIVER_NAME "SSD1289"
#define GDISP_HARDWARE_CLEARS TRUE
#define GDISP_HARDWARE_FILLS TRUE
#define GDISP_HARDWARE_BITFILLS TRUE
#define GDISP_HARDWARE_SCROLL TRUE
#define GDISP_HARDWARE_PIXELREAD TRUE
#define GDISP_HARDWARE_CONTROL TRUE
#define GDISP_DRIVER_STRUCT GDISP_SSD1289
#define GDISP_HARDWARE_STREAM_WRITE TRUE
#define GDISP_HARDWARE_STREAM_READ TRUE
#define GDISP_HARDWARE_CONTROL TRUE
#if defined(GDISP_USE_DMA)
#define GDISP_HARDWARE_FILLS TRUE
#define GDISP_HARDWARE_BITFILLS TRUE
#endif
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565

View File

@ -463,7 +463,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
#endif
#if GDISP_HARDWARE_BITFILLS
void gdisp_lld_blit_area(GDISPDriver *g) {
LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
BITMAPV4HEADER bmpInfo;
HDC dcScreen;
pixel_t * buffer;
@ -577,7 +577,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
#endif
#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
void gdisp_lld_vertical_scroll(GDISPDriver *g) {
LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
HDC dcScreen;
RECT rect;
coord_t lines;

View File

@ -14,6 +14,9 @@
#if GFX_USE_GDISP
#define GDISP_LLD_DECLARATIONS
#include "gdisp/lld/gdisp_lld.h"
/**
* Our color model - Default or 24 bit only.
*
@ -25,19 +28,6 @@
#define GDISP_FORCE_24BIT FALSE
#endif
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
#include "ginput/lld/mouse.h"
#endif
/* Include the emulation code for things we don't support */
#include "gdisp/lld/emulation.c"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 480
#endif
@ -45,6 +35,16 @@
#define GDISP_SCREEN_WIDTH 640
#endif
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
#include "ginput/lld/mouse.h"
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
Display *dis;
int scr;
Window win;
@ -130,7 +130,7 @@ static int FatalXIOError(Display *d) {
exit(0);
}
bool_t gdisp_lld_init(void)
LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
{
XSizeHints *pSH;
XSetWindowAttributes xa;
@ -212,69 +212,81 @@ bool_t gdisp_lld_init(void)
gfxThreadClose(hth);
/* Initialise the GDISP structure to match */
GDISP.Orientation = GDISP_ROTATE_0;
GDISP.Powermode = powerOn;
GDISP.Backlight = 100;
GDISP.Contrast = 50;
GDISP.Width = GDISP_SCREEN_WIDTH;
GDISP.Height = GDISP_SCREEN_HEIGHT;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
GDISP.clipx0 = 0;
GDISP.clipy0 = 0;
GDISP.clipx1 = GDISP.Width;
GDISP.clipy1 = GDISP.Height;
#endif
g->g.Orientation = g->g_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = 100;
g->g.Contrast = 50;
g->g.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
return TRUE;
}
void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
{
XColor col;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
// Clip pre orientation change
if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
#endif
col.red = RED_OF(color) << 8;
col.green = GREEN_OF(color) << 8;
col.blue = BLUE_OF(color) << 8;
col.red = RED_OF(g->p.color) << 8;
col.green = GREEN_OF(g->p.color) << 8;
col.blue = BLUE_OF(g->p.color) << 8;
XAllocColor(dis, cmap, &col);
XSetForeground(dis, gc, col.pixel);
XDrawPoint(dis, pix, gc, (int)x, (int)y );
XDrawPoint(dis, win, gc, (int)x, (int)y );
XDrawPoint(dis, pix, gc, (int)g->p.x, (int)g->p.y );
XDrawPoint(dis, win, gc, (int)g->p.x, (int)g->p.y );
XFlush(dis);
}
void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
XColor col;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
// Clip pre orientation change
if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
#endif
#if GDISP_HARDWARE_FILLS
LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
XColor col;
col.red = RED_OF(color) << 8;
col.green = GREEN_OF(color) << 8;
col.blue = BLUE_OF(color) << 8;
XAllocColor(dis, cmap, &col);
XSetForeground(dis, gc, col.pixel);
XFillRectangle(dis, pix, gc, x, y, cx, cy);
XFillRectangle(dis, win, gc, x, y, cx, cy);
XFlush(dis);
}
col.red = RED_OF(g->p.color) << 8;
col.green = GREEN_OF(g->p.color) << 8;
col.blue = BLUE_OF(g->p.color) << 8;
XAllocColor(dis, cmap, &col);
XSetForeground(dis, gc, col.pixel);
XFillRectangle(dis, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
XFillRectangle(dis, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
XFlush(dis);
}
#endif
// Start of Bitblit code
//XImage bitmap;
//pixel_t *bits;
// bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
// bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
// 0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
// 0, 0);
#if 0 && GDISP_HARDWARE_BITFILLS
LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
// Start of Bitblit code
//XImage bitmap;
//pixel_t *bits;
// bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
// bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
// 0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
// 0, 0);
}
#endif
#if GDISP_HARDWARE_PIXELREAD
LLDSPEC color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
XColor color;
XImage *img;
img = XGetImage (dis, pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
color->pixel = XGetPixel (img, 0, 0);
XFree(img);
XQueryColor(dis, cmap, &color);
return RGB2COLOR(c.red>>8, c.green>>8, c.blue>>8);
}
#endif
#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
if (g->p.y1 > 0) {
XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
XCopyArea(dis, pix, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
} else {
XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-lines, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
}
}
#endif
#if GINPUT_NEED_MOUSE

View File

@ -23,17 +23,14 @@
/*===========================================================================*/
#define GDISP_DRIVER_NAME "Linux emulator - X11"
#define GDISP_DRIVER_STRUCT GDISP_X11
#define GDISP_HARDWARE_CLEARS FALSE
#define GDISP_HARDWARE_DRAWPIXEL TRUE
#define GDISP_HARDWARE_FILLS TRUE
#define GDISP_HARDWARE_BITFILLS FALSE
#define GDISP_HARDWARE_SCROLL FALSE
#define GDISP_HARDWARE_PIXELREAD FALSE
#define GDISP_HARDWARE_SCROLL TRUE
#define GDISP_HARDWARE_PIXELREAD TRUE
#define GDISP_HARDWARE_CONTROL FALSE
#define GDISP_HARDWARE_CIRCLES FALSE
#define GDISP_HARDWARE_CIRCLEFILLS FALSE
#define GDISP_HARDWARE_ARCS FALSE
#define GDISP_HARDWARE_ARCFILLS FALSE
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888

View File

@ -33,26 +33,26 @@
* @{
*/
/**
* @brief Hardware streaming interface is supported.
* @brief Hardware streaming writing is supported.
* @details If set to @p FALSE software emulation is used.
* @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
* @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
*/
#ifndef GDISP_HARDWARE_STREAM
#define GDISP_HARDWARE_STREAM FALSE
#ifndef GDISP_HARDWARE_STREAM_WRITE
#define GDISP_HARDWARE_STREAM_WRITE FALSE
#endif
/**
* @brief Hardware streaming requires an explicit end call.
* @details If set to @p FALSE if an explicit stream end call is not required.
* @brief Hardware streaming reading of the display surface is supported.
* @details If set to @p FALSE this routine is not available.
*/
#ifndef GDISP_HARDWARE_STREAM_STOP
#define GDISP_HARDWARE_STREAM_STOP FALSE
#ifndef GDISP_HARDWARE_STREAM_READ
#define GDISP_HARDWARE_STREAM_READ FALSE
#endif
/**
* @brief Hardware accelerated draw pixel.
* @details If set to @p FALSE software emulation is used.
* @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
* @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
*/
#ifndef GDISP_HARDWARE_DRAWPIXEL
#define GDISP_HARDWARE_DRAWPIXEL FALSE
@ -178,7 +178,7 @@ typedef struct GDISPDriver {
coord_t clipx1, clipy1;
} t;
#endif
#if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM && GDISP_HARDWARE_BITFILLS))
#if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM_WRITE && GDISP_HARDWARE_BITFILLS))
// A pixel line buffer
color_t linebuf[GDISP_LINEBUF_SIZE];
#endif
@ -204,10 +204,10 @@ typedef struct GDISPDriver {
*/
LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g);
#if GDISP_HARDWARE_STREAM || defined(__DOXYGEN__)
#if GDISP_HARDWARE_STREAM_WRITE || defined(__DOXYGEN__)
/**
* @brief Start a streamed operation
* @pre GDISP_HARDWARE_STREAM is TRUE
* @brief Start a streamed write operation
* @pre GDISP_HARDWARE_STREAM_WRITE is TRUE
*
* @param[in] g The driver structure
* @param[in] g->p.x,g->p.y The window position
@ -217,44 +217,68 @@ typedef struct GDISPDriver {
* @note Streaming operations that wrap the defined window have
* undefined results.
*/
LLDSPEC void gdisp_lld_stream_start(GDISPDriver *g);
LLDSPEC void gdisp_lld_write_start(GDISPDriver *g);
/**
* @brief Send a pixel to the current streaming position and then increment that position
* @pre GDISP_HARDWARE_STREAM is TRUE
* @pre GDISP_HARDWARE_STREAM_WRITE is TRUE
*
* @param[in] g The driver structure
* @param[in] g->p.color The color to display at the curent position
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC void gdisp_lld_stream_color(GDISPDriver *g);
LLDSPEC void gdisp_lld_write_color(GDISPDriver *g);
#if GDISP_HARDWARE_STREAM_READ || defined(__DOXYGEN__)
/**
* @brief Read a pixel from the current streaming position and then increment that position
* @return The color at the current position
* @pre GDISP_HARDWARE_STREAM and GDISP_HARDWARE_STREAM_READ is TRUE
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC color_t gdisp_lld_stream_read(GDISPDriver *g);
#endif
#if GDISP_HARDWARE_STREAM_STOP || defined(__DOXYGEN__)
/**
* @brief End the current streaming operation
* @pre GDISP_HARDWARE_STREAM and GDISP_HARDWARE_STREAM_STOP is TRUE
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC void gdisp_lld_stream_stop(GDISPDriver *g);
#endif
/**
* @brief End the current streaming write operation
* @pre GDISP_HARDWARE_STREAM_WRITE is TRUE
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC void gdisp_lld_write_stop(GDISPDriver *g);
#endif
#if GDISP_HARDWARE_STREAM_READ || defined(__DOXYGEN__)
/**
* @brief Start a streamed read operation
* @pre GDISP_HARDWARE_STREAM_READ is TRUE
*
* @param[in] g The driver structure
* @param[in] g->p.x,g->p.y The window position
* @param[in] g->p.cx,g->p.cy The window size
*
* @note The parameter variables must not be altered by the driver.
* @note Streaming operations that wrap the defined window have
* undefined results.
*/
LLDSPEC void gdisp_lld_read_start(GDISPDriver *g);
/**
* @brief Read a pixel from the current streaming position and then increment that position
* @return The color at the current position
* @pre GDISP_HARDWARE_STREAM_READ is TRUE
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC color_t gdisp_lld_read_color(GDISPDriver *g);
/**
* @brief End the current streaming operation
* @pre GDISP_HARDWARE_STREAM_READ is TRUE
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC void gdisp_lld_read_stop(GDISPDriver *g);
#endif
#if GDISP_HARDWARE_DRAWPIXEL || defined(__DOXYGEN__)
/**
* @brief Draw a pixel
@ -399,10 +423,12 @@ typedef struct GDISPDriver {
typedef struct GDISPVMT {
bool_t (*init)(GDISPDriver *g);
void (*streamstart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy
void (*streamcolor)(GDISPDriver *g); // Uses p.color
color_t (*streamread)(GDISPDriver *g); // Uses no parameters
void (*streamstop)(GDISPDriver *g); // Uses no parameters
void (*writestart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy
void (*writecolor)(GDISPDriver *g); // Uses p.color
void (*writestop)(GDISPDriver *g); // Uses no parameters
void (*readstart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy
color_t (*readcolor)(GDISPDriver *g); // Uses no parameters
void (*readstop)(GDISPDriver *g); // Uses no parameters
void (*pixel)(GDISPDriver *g); // Uses p.x,p.y p.color
void (*clear)(GDISPDriver *g); // Uses p.color
void (*fill)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy p.color
@ -418,15 +444,17 @@ typedef struct GDISPDriver {
#define GDISP_DRIVER_STRUCT_INIT {{0}, &VMT}
static const GDISPVMT VMT = {
gdisp_lld_init,
#if GDISP_HARDWARE_STREAM
gdisp_lld_stream_start,
gdisp_lld_stream_color,
gdisp_lld_stream_read,
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop,
#else
0,
#endif
#if GDISP_HARDWARE_STREAM_WRITE
gdisp_lld_write_start,
gdisp_lld_write_color,
gdisp_lld_write_stop,
#else
0, 0, 0,
#endif
#if GDISP_HARDWARE_STREAM_READ
gdisp_lld_read_start,
gdisp_lld_read_color,
gdisp_lld_read_stop,
#else
0, 0, 0,
#endif
@ -480,10 +508,12 @@ typedef struct GDISPDriver {
#else
#define gdisp_lld_init(g) g->vmt->init(g)
#define gdisp_lld_stream_start(g) g->vmt->streamstart(g)
#define gdisp_lld_stream_color(g) g->vmt->streamcolor(g)
#define gdisp_lld_stream_read(g) g->vmt->streamread(g)
#define gdisp_lld_stream_stop(g) g->vmt->streamstop(g)
#define gdisp_lld_write_start(g) g->vmt->writestart(g)
#define gdisp_lld_write_color(g) g->vmt->writecolor(g)
#define gdisp_lld_write_stop(g) g->vmt->writestop(g)
#define gdisp_lld_read_start(g) g->vmt->readstart(g)
#define gdisp_lld_read_color(g) g->vmt->readcolor(g)
#define gdisp_lld_read_stop(g) g->vmt->readstop(g)
#define gdisp_lld_draw_pixel(g) g->vmt->pixel(g)
#define gdisp_lld_clear(g) g->vmt->clear(g)
#define gdisp_lld_fill_area(g) g->vmt->fill(g)

View File

@ -19,8 +19,8 @@
/* Include the low level driver information */
#include "gdisp/lld/gdisp_lld.h"
#if !GDISP_HARDWARE_STREAM && !GDISP_HARDWARE_DRAWPIXEL
#error "GDISP Driver: Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be defined"
#if !GDISP_HARDWARE_STREAM_WRITE && !GDISP_HARDWARE_DRAWPIXEL
#error "GDISP Driver: Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be defined"
#endif
#if 1
@ -48,15 +48,6 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#define MUTEX_EXIT()
#endif
#if GDISP_HARDWARE_STREAM_STOP
#define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \
gdisp_lld_stream_stop(GC); \
GC->flags &= ~GDISP_FLG_INSTREAM; \
}
#else
#define STREAM_CLEAR() GC->flags &= ~GDISP_FLG_INSTREAM
#endif
#define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP))
/*==========================================================================*/
@ -85,11 +76,9 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#endif
GC->p.cx = GC->p.cy = 1;
gdisp_lld_stream_start(GC);
gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_start(GC);
gdisp_lld_write_color(GC);
gdisp_lld_write_stop(GC);
}
#endif
@ -100,19 +89,17 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#if GDISP_HARDWARE_FILLS
// Best is hardware accelerated area fill
#define fillarea() gdisp_lld_fill_area(GC)
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is hardware streaming
static INLINE void fillarea(void) {
uint32_t area;
area = (uint32_t)GC->p.cx * GC->p.cy;
gdisp_lld_stream_start(GC);
gdisp_lld_write_start(GC);
for(; area; area--)
gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_color(GC);
gdisp_lld_write_stop(GC);
}
#else
// Worst is drawing pixels
@ -159,7 +146,7 @@ static void hline_clip(void) {
// This is an optimization for the point case. It is only worthwhile however if we
// have hardware fills or if we support both hardware pixel drawing and hardware streaming
#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM)
#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE)
// Is this a point
if (GC->p.x == GC->p.x1) {
#if GDISP_HARDWARE_DRAWPIXEL
@ -168,11 +155,9 @@ static void hline_clip(void) {
#else
// Worst is streaming
GC->p.cx = GC->p.cy = 1;
gdisp_lld_stream_start(GC);
gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_start(GC);
gdisp_lld_write_color(GC);
gdisp_lld_write_stop(GC);
#endif
return;
}
@ -183,15 +168,13 @@ static void hline_clip(void) {
GC->p.cx = GC->p.x1 - GC->p.x + 1;
GC->p.cy = 1;
gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is streaming
GC->p.cx = GC->p.x1 - GC->p.x + 1;
GC->p.cy = 1;
gdisp_lld_stream_start(GC);
do { gdisp_lld_stream_color(GC); } while(GC->p.cx--);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_start(GC);
do { gdisp_lld_write_color(GC); } while(GC->p.cx--);
gdisp_lld_write_stop(GC);
#else
// Worst is drawing pixels
for(; GC->p.x <= GC->p.x1; GC->p.x++)
@ -217,7 +200,7 @@ static void vline_clip(void) {
// This is an optimization for the point case. It is only worthwhile however if we
// have hardware fills or if we support both hardware pixel drawing and hardware streaming
#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM)
#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE)
// Is this a point
if (GC->p.y == GC->p.y1) {
#if GDISP_HARDWARE_DRAWPIXEL
@ -226,11 +209,9 @@ static void vline_clip(void) {
#else
// Worst is streaming
GC->p.cx = GC->p.cy = 1;
gdisp_lld_stream_start(GC);
gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_start(GC);
gdisp_lld_write_color(GC);
gdisp_lld_write_stop(GC);
#endif
return;
}
@ -241,15 +222,13 @@ static void vline_clip(void) {
GC->p.cy = GC->p.y1 - GC->p.y + 1;
GC->p.cx = 1;
gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is streaming
GC->p.cy = GC->p.y1 - GC->p.y + 1;
GC->p.cx = 1;
gdisp_lld_stream_start(GC);
do { gdisp_lld_stream_color(GC); } while(GC->p.cy--);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_start(GC);
do { gdisp_lld_write_color(GC); } while(GC->p.cy--);
gdisp_lld_write_stop(GC);
#else
// Worst is drawing pixels
for(; GC->p.y <= GC->p.y1; GC->p.y++)
@ -377,13 +356,13 @@ void _gdispInit(void) {
GC->flags |= GDISP_FLG_INSTREAM;
#if GDISP_HARDWARE_STREAM
#if GDISP_HARDWARE_STREAM_WRITE
// Best is hardware streaming
GC->p.x = x;
GC->p.y = y;
GC->p.cx = cx;
GC->p.cy = cy;
gdisp_lld_stream_start(GC);
gdisp_lld_write_start(GC);
#else
// Worst - save the parameters and use pixel drawing
@ -402,7 +381,7 @@ void _gdispInit(void) {
}
void gdispStreamColor(color_t color) {
#if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
#if !GDISP_HARDWARE_STREAM_WRITE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
coord_t sx1, sy1;
#endif
@ -412,10 +391,10 @@ void _gdispInit(void) {
if (!(GC->flags & GDISP_FLG_INSTREAM))
return;
#if GDISP_HARDWARE_STREAM
#if GDISP_HARDWARE_STREAM_WRITE
// Best is hardware streaming
GC->p.color = color;
gdisp_lld_stream_color(GC);
gdisp_lld_write_color(GC);
#elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
GC->linebuf[GC->p.cx++] = color;
if (GC->p.cx >= GDISP_LINEBUF_SIZE) {
@ -494,10 +473,8 @@ void _gdispInit(void) {
if (!(GC->flags & GDISP_FLG_INSTREAM))
return;
#if GDISP_HARDWARE_STREAM
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
#if GDISP_HARDWARE_STREAM_WRITE
gdisp_lld_write_stop(GC);
#elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
if (GC->p.cx) {
GC->p.x1 = 0;
@ -553,7 +530,7 @@ void gdispClear(color_t color) {
GC->p.cy = GC->g.Height;
GC->p.color = color;
gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is streaming
uint32_t area;
@ -563,12 +540,10 @@ void gdispClear(color_t color) {
GC->p.color = color;
area = (uint32_t)GC->p.cx * GC->p.cy;
gdisp_lld_stream_start(GC);
gdisp_lld_write_start(GC);
for(; area; area--)
gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_color(GC);
gdisp_lld_write_stop(GC);
#else
// Worst is drawing pixels
GC->p.color = color;
@ -616,7 +591,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.x2 = srccx;
GC->p.ptr = (void *)buffer;
gdisp_lld_blit_area(GC);
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is hardware streaming
// Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap
@ -629,16 +604,14 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.y = y;
GC->p.cx = cx;
GC->p.cy = cy;
gdisp_lld_stream_start(GC);
gdisp_lld_write_start(GC);
for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) {
for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) {
GC->p.color = *buffer++;
gdisp_lld_stream_color(GC);
gdisp_lld_write_color(GC);
}
}
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_stop(GC);
#elif GDISP_HARDWARE_FILLS
// Only slightly better than drawing pixels is to look for runs and use fill area
@ -1578,17 +1551,15 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.x = x;
GC->p.y = y;
c = gdisp_lld_get_pixel_color(GC);
#elif GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ
#elif GDISP_HARDWARE_STREAM_READ
// Next best is hardware streaming
GC->p.x = x;
GC->p.y = y;
GC->p.cx = 1;
GC->p.cy = 1;
gdisp_lld_stream_start(GC);
c = gdisp_lld_stream_read(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_read_start(GC);
c = gdisp_lld_read_color(GC);
gdisp_lld_read_stop(GC);
#else
// Worst is "not possible"
#error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display"
@ -1634,7 +1605,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
#else
cy -= abslines;
if (lines < 0) {
fy = y+cx-1;
fy = y+cy-1;
dy = -1;
} else {
fy = y;
@ -1652,18 +1623,16 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
fx = GDISP_LINEBUF_SIZE;
// Read one line of data from the screen
#if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ
#if GDISP_HARDWARE_STREAM_READ
// Best is hardware streaming
GC->p.x = x+ix;
GC->p.y = fy+lines;
GC->p.cx = fx;
GC->p.cy = 1;
gdisp_lld_stream_start(GC);
gdisp_lld_read_start(GC);
for(j=0; j < fx; j++)
GC->linebuf[j] = gdisp_lld_stream_read(GC);
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
GC->linebuf[j] = gdisp_lld_read_color(GC);
gdisp_lld_read_stop(GC);
#elif GDISP_HARDWARE_PIXELREAD
// Next best is single pixel reads
for(j=0; j < fx; j++) {
@ -1688,20 +1657,18 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.x2 = fx;
GC->p.ptr = (void *)GC->linebuf;
gdisp_lld_blit_area(GC);
#elif GDISP_HARDWARE_STREAM
#elif GDISP_HARDWARE_STREAM_WRITE
// Next best is hardware streaming
GC->p.x = x+ix;
GC->p.y = fy;
GC->p.cx = fx;
GC->p.cy = 1;
gdisp_lld_stream_start(GC);
gdisp_lld_write_start(GC);
for(j = 0; j < fx; j++) {
GC->p.color = GC->linebuf[j];
gdisp_lld_stream_color(GC);
gdisp_lld_write_color(GC);
}
#if GDISP_HARDWARE_STREAM_STOP
gdisp_lld_stream_stop(GC);
#endif
gdisp_lld_write_stop(GC);
#else
// Worst is drawing pixels
GC->p.y = fy;