Partially handle screen rotation using remapping

Use row and column remapping to change either row or column addressing
for each orientation.  This removes the need to reverse the drawing
direction of either x or y in the drawing routines.  However in the 90
and 270 case x and y must still be swapped.

Also, rename the SSD1306 remapping command names so they are more
descriptive.
This commit is contained in:
ergosys 2014-12-13 14:34:34 -08:00
parent 7285477f13
commit 9618d7917b
2 changed files with 45 additions and 48 deletions

View File

@ -33,10 +33,11 @@
#define SSD1306_HV_PAGE_ADDRESS 0x22 #define SSD1306_HV_PAGE_ADDRESS 0x22
#define SSD1306_PAM_PAGE_START 0xB0 #define SSD1306_PAM_PAGE_START 0xB0
#define SSD1306_COMSCANINC 0xC0 #define SSD1306_ROWSCANINC 0xC0
#define SSD1306_COMSCANDEC 0xC8 #define SSD1306_ROWSCANDEC 0xC8
#define SSD1306_SEGREMAP 0xA0 #define SSD1306_COLSCANINC 0xA0
#define SSD1306_COLSCANDEC 0xA1
#define SSD1306_CHARGEPUMP 0x8D #define SSD1306_CHARGEPUMP 0x8D

View File

@ -105,8 +105,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
write_cmd(g, SSD1306_SETSTARTLINE | 0); write_cmd(g, SSD1306_SETSTARTLINE | 0);
write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14); write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14);
write_cmd2(g, SSD1306_MEMORYMODE, 0); write_cmd2(g, SSD1306_MEMORYMODE, 0);
write_cmd(g, SSD1306_SEGREMAP+1); write_cmd(g, SSD1306_COLSCANDEC);
write_cmd(g, SSD1306_COMSCANDEC); write_cmd(g, SSD1306_ROWSCANDEC);
#if GDISP_SCREEN_HEIGHT == 64 #if GDISP_SCREEN_HEIGHT == 64
write_cmd2(g, SSD1306_SETCOMPINS, 0x12); write_cmd2(g, SSD1306_SETCOMPINS, 0x12);
#else #else
@ -168,26 +168,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
#if GDISP_HARDWARE_DRAWPIXEL #if GDISP_HARDWARE_DRAWPIXEL
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
coord_t x, y; coord_t x = g->p.x;
coord_t y = g->p.y;
switch(g->g.Orientation) { if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) {
default: coord_t tmp;
case GDISP_ROTATE_0: tmp = x; x = y; y = tmp;
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) != Black)
RAM(g)[xyaddr(x, y)] |= xybit(y); RAM(g)[xyaddr(x, y)] |= xybit(y);
@ -199,26 +184,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
#if GDISP_HARDWARE_PIXELREAD #if GDISP_HARDWARE_PIXELREAD
LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
coord_t x, y; coord_t x = g->p.x;
coord_t y = g->p.y;
switch(g->g.Orientation) { if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) {
default: coord_t tmp;
case GDISP_ROTATE_0: tmp = x; x = y; y = tmp;
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; return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
} }
@ -252,8 +222,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
case GDISP_CONTROL_ORIENTATION: case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr) if (g->g.Orientation == (orientation_t)g->p.ptr)
return; return;
switch((orientation_t)g->p.ptr) { orientation_t orient = (orientation_t)g->p.ptr;
/* Rotation is handled by the drawing routines */ switch(orient) {
case GDISP_ROTATE_0: case GDISP_ROTATE_0:
case GDISP_ROTATE_180: case GDISP_ROTATE_180:
g->g.Height = GDISP_SCREEN_HEIGHT; g->g.Height = GDISP_SCREEN_HEIGHT;
@ -267,7 +237,33 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
default: default:
return; return;
} }
g->g.Orientation = (orientation_t)g->p.ptr; // 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;
return; return;
case GDISP_CONTROL_CONTRAST: case GDISP_CONTROL_CONTRAST: