From 05354e057d59b3d6fe47a6e3c0c979080b091108 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 16 Dec 2014 23:07:14 +1000 Subject: [PATCH] Had to revert the new method of orientation support for SSD1306. Unfortunately the new method immediately flipped orientation rather than just affecting drawing operations. As both methods can be supported by the hardware/code we always use drawing only orientation support. Updated the new fill routine to match. Also fixed color black bug and moved variable definitions to start of a block as is required by pure C compilers. --- drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c | 140 +++++++++++++--------- 1 file changed, 85 insertions(+), 55 deletions(-) diff --git a/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c index a13b82a8..d2f2a872 100644 --- a/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c +++ b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c @@ -159,7 +159,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { #if GDISP_HARDWARE_CLEARS LLDSPEC void gdisp_lld_clear(GDisplay *g) { - uint8_t fill = (gdispColor2Native(g->p.color) == Black) ? 0 : 0xff; + uint8_t fill = (gdispColor2Native(g->p.color) == gdispColor2Native(Black)) ? 0 : 0xff; int bytes = GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT/8; memset(RAM(g), fill, bytes); g->flags |= GDISP_FLG_NEEDFLUSH; @@ -168,21 +168,47 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { #if GDISP_HARDWARE_FILLS LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { - coord_t sy = g->p.y; - coord_t ey = sy + g->p.cy - 1; - coord_t sx = g->p.x; - coord_t ex = g->p.x + g->p.cx - 1; - if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { - coord_t tmp; - tmp = sx; sx = sy; sy = tmp; - tmp = ex; ex = ey; ey = tmp; + coord_t sy, ey; + coord_t sx, ex; + coord_t col; + unsigned spage, zpages; + uint8_t * base; + uint8_t mask; + + switch(g->g.Orientation) { + default: + case GDISP_ROTATE_0: + sx = g->p.x; + ex = g->p.x + g->p.cx - 1; + sy = g->p.y; + ey = sy + g->p.cy - 1; + break; + case GDISP_ROTATE_90: + sx = g->p.y; + ex = g->p.y + g->p.cy - 1; + sy = GDISP_SCREEN_HEIGHT - g->p.x - g->p.cx; + ey = GDISP_SCREEN_HEIGHT-1 - g->p.x; + break; + case GDISP_ROTATE_180: + sx = GDISP_SCREEN_WIDTH - g->p.x - g->p.cx; + ex = GDISP_SCREEN_WIDTH-1 - g->p.x; + sy = GDISP_SCREEN_HEIGHT - g->p.y - g->p.cy; + ey = GDISP_SCREEN_HEIGHT-1 - g->p.y; + break; + case GDISP_ROTATE_270: + sx = GDISP_SCREEN_WIDTH - g->p.y - g->p.cy; + ex = GDISP_SCREEN_WIDTH-1 - g->p.y; + sy = g->p.x; + ey = g->p.x + g->p.cx - 1; + break; } - unsigned spage = sy / 8; - uint8_t * base = RAM(g) + GDISP_SCREEN_WIDTH * spage; - uint8_t mask = 0xff << (sy&7); - unsigned zpages = (ey / 8) - spage; - coord_t col; - if (gdispColor2Native(g->p.color)==Black) { + + spage = sy / 8; + base = RAM(g) + GDISP_SCREEN_WIDTH * spage; + mask = 0xff << (sy&7); + zpages = (ey / 8) - spage; + + if (gdispColor2Native(g->p.color) == gdispColor2Native(Black)) { while (zpages--) { for (col = sx; col <= ex; col++) base[col] &= ~mask; @@ -208,13 +234,28 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { #if GDISP_HARDWARE_DRAWPIXEL LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { - coord_t x = g->p.x; - coord_t y = g->p.y; - if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { - coord_t tmp; - tmp = x; x = y; y = tmp; + coord_t x, y; + + switch(g->g.Orientation) { + default: + case GDISP_ROTATE_0: + x = g->p.x; + y = g->p.y; + break; + case GDISP_ROTATE_90: + x = g->p.y; + y = GDISP_SCREEN_HEIGHT-1 - g->p.x; + break; + case GDISP_ROTATE_180: + x = GDISP_SCREEN_WIDTH-1 - g->p.x; + y = GDISP_SCREEN_HEIGHT-1 - g->p.y; + break; + case GDISP_ROTATE_270: + x = GDISP_SCREEN_WIDTH-1 - g->p.y; + y = g->p.x; + break; } - if (gdispColor2Native(g->p.color) != Black) + if (gdispColor2Native(g->p.color) != gdispColor2Native(Black)) RAM(g)[xyaddr(x, y)] |= xybit(y); else RAM(g)[xyaddr(x, y)] &= ~xybit(y); @@ -224,11 +265,26 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { #if GDISP_HARDWARE_PIXELREAD LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { - coord_t x = g->p.x; - coord_t y = g->p.y; - if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { - coord_t tmp; - tmp = x; x = y; y = tmp; + coord_t x, y; + + switch(g->g.Orientation) { + default: + case GDISP_ROTATE_0: + x = g->p.x; + y = g->p.y; + break; + case GDISP_ROTATE_90: + x = g->p.y; + y = GDISP_SCREEN_HEIGHT-1 - g->p.x; + break; + case GDISP_ROTATE_180: + x = GDISP_SCREEN_WIDTH-1 - g->p.x; + y = GDISP_SCREEN_HEIGHT-1 - g->p.y; + break; + case GDISP_ROTATE_270: + x = GDISP_SCREEN_WIDTH-1 - g->p.y; + y = g->p.x; + break; } return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black; } @@ -262,8 +318,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { case GDISP_CONTROL_ORIENTATION: if (g->g.Orientation == (orientation_t)g->p.ptr) return; - orientation_t orient = (orientation_t)g->p.ptr; - switch(orient) { + switch((orientation_t)g->p.ptr) { + /* Rotation is handled by the drawing routines */ case GDISP_ROTATE_0: case GDISP_ROTATE_180: g->g.Height = GDISP_SCREEN_HEIGHT; @@ -277,33 +333,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { default: return; } - // Remap the rows and columns according to orientation. This just - // eliminates the need to reverse x or y directions in the drawing - // routines. There is still the need to swap x and y for 90 and 270. - // However, without these, the hardware fill routine would be much - // more complicated. - acquire_bus(g); - switch(orient) { - default: - case GDISP_ROTATE_0: - write_cmd(g, SSD1306_COLSCANDEC); - write_cmd(g, SSD1306_ROWSCANDEC); - break; - case GDISP_ROTATE_180: - write_cmd(g, SSD1306_COLSCANINC); - write_cmd(g, SSD1306_ROWSCANINC); - break; - case GDISP_ROTATE_90: - write_cmd(g, SSD1306_COLSCANDEC); - write_cmd(g, SSD1306_ROWSCANINC); - break; - case GDISP_ROTATE_270: - write_cmd(g, SSD1306_COLSCANINC); - write_cmd(g, SSD1306_ROWSCANDEC); - break; - } - release_bus(g); - g->g.Orientation = orient; + g->g.Orientation = (orientation_t)g->p.ptr; return; case GDISP_CONTROL_CONTRAST: