Fork of Chris Styles' C12832 LCD driver
Dependents: co657_lcdplay co657_nrf52_beacons door_lock co657_IoT
Fork of C12832 by
Diff: C12832.cpp
- Revision:
- 18:8c294697c901
- Parent:
- 17:67f9ca828270
- Child:
- 19:de1f73b31288
--- a/C12832.cpp Wed Oct 28 21:01:40 2015 +0000 +++ b/C12832.cpp Sun Nov 01 02:22:53 2015 +0000 @@ -17,6 +17,9 @@ // 25.10.12 add standart font // 20.12.12 add bitmap graphics +// Assorted changes/updates by Fred Barnes, University of Kent <frmb@kent.ac.uk> +// 31.10.15 minor bugfixes, some drawing optimisation + // optional defines : // #define debug_lcd 1 @@ -137,19 +140,39 @@ // set one pixel in buffer -void C12832::pixel(int x, int y, int color) +void C12832::pixel (int x, int y, int color) { - // first check parameter - if(x > 128 || y > 32 || x < 0 || y < 0) return; + if ((x >= 128) || (y >= 32) || (x < 0) || (y < 0)) { + /* out of bounds */ + return; + } - if(draw_mode == NORMAL) { - if(color == 0) - buffer[x + ((y/8) * 128)] &= ~(1 << (y%8)); // erase pixel - else - buffer[x + ((y/8) * 128)] |= (1 << (y%8)); // set pixel + if (draw_mode == NORMAL) { + if (color == 0) { + buffer[x + ((y >> 3) << 7)] &= ~(1 << (y & 0x07)); // erase pixel + } else { + buffer[x + ((y >> 3) << 7)] |= (1 << (y & 0x07)); // set pixel + } } else { // XOR mode - if(color == 1) - buffer[x + ((y/8) * 128)] ^= (1 << (y%8)); // xor pixel + if (color == 1) { + buffer[x + ((y >> 3) << 7)] ^= (1 << (y & 0x07)); // xor pixel + } + } +} + +/* plots a pixel, but without bounds checking (assumed to be done elsewhere) */ +void C12832::pixel_nochk (int x, int y, int colour) +{ + if (draw_mode == NORMAL) { + if (colour == 0) { + buffer[x + ((y >> 3) << 7)] &= ~(1 << (y & 0x07)); // erase pixel + } else { + buffer[x + ((y >> 3) << 7)] |= (1 << (y & 0x07)); // set pixel + } + } else { // XOR mode + if (colour == 1) { + buffer[x + ((y >> 3) << 7)] ^= (1 << (y & 0x07)); // xor pixel + } } } @@ -201,103 +224,214 @@ } -void C12832::cls(void) +void C12832::cls (void) { - memset(buffer,0x00,512); // clear display buffer - if (auto_up) copy_to_lcd(); + memset (buffer, 0x00, 512); // clear display buffer + if (auto_up) { + copy_to_lcd(); + } } - -void C12832::line(int x0, int y0, int x1, int y1, int color) +/* + * based on Foley and van Dam, Computer Graphics Principles and Practice, + * Second edition in C, Fig 3.8 + * + * Adapted back into C from David Wood's occam implementation (line.occ). + */ +void C12832::line (int x0, int y0, int x1, int y1, int colour) { - int dx = 0, dy = 0; - int dx_sym = 0, dy_sym = 0; - int dx_x2 = 0, dy_x2 = 0; - int di = 0; + int dx = x1 - x0; + int dy = y1 - y0; + int x, y, a_dx, s_x, a_dy, s_y; + int d, strt, diag; - dx = x1-x0; - dy = y1-y0; - - if (dx == 0) { /* vertical line */ - if (y1 > y0) vline(x0,y0,y1,color); - else vline(x0,y1,y0,color); + + if (dx == 0) { + /* vertical line */ + if (y0 > y1) { + vline (x0, y1, y0, colour); + } else { + vline (x0, y0, y1, colour); + } return; - } else if (dy == 0) { /* horizontal line */ - if (x1 > x0) hline(x0,y0,x1,color); - else hline(x1,y0,x0,color); + } + if (dy == 0) { + /* horizontal line */ + if (x0 > x1) { + hline (x1, y0, x0, colour); + } else { + hline (x0, y0, x1, colour); + } + return; + } + + if ((x0 >= 128) || (x0 < 0) || (y0 >= 32) || (y0 < 0)) { + /* starts outside raster, so abort */ return; } - + + x = x0; + y = y0; if (dx > 0) { - dx_sym = 1; + a_dx = dx; s_x = 1; } else { - dx_sym = -1; + a_dx = -dx; s_x = -1; + } + if (dy > 0) { + a_dy = dy; s_y = 1; + } else { + a_dy = -dy; s_y = -1; } + + if (a_dx > a_dy) { + strt = a_dy * 2; /* straight */ + diag = strt - (2 * a_dx); /* diagonal */ + d = strt - a_dx; - if (dy > 0) { - dy_sym = 1; + while ((a_dx >= 0) && (x >= 0) && (x < 128) && (y >= 0) && (y < 32)) { + pixel_nochk (x, y, colour); + x += s_x; + a_dx--; + + if (d <= 0) { + d += strt; + } else { + d += diag; + y += s_y; + } + } } else { - dy_sym = -1; + strt = a_dx * 2; /* straight */ + diag = strt - (2 * a_dy); /* diagonal */ + d = strt - a_dy; + + while ((a_dy >= 0) && (x >= 0) && (x < 128) && (y >= 0) && (y < 32)) { + pixel_nochk (x, y, colour); + y += s_y; + a_dy--; + + if (d <= 0) { + d += strt; + } else { + d += diag; + x += s_x; + } + } } - dx = dx_sym*dx; - dy = dy_sym*dy; - - dx_x2 = dx*2; - dy_x2 = dy*2; - - if (dx >= dy) { - di = dy_x2 - dx; - while (x0 != x1) { - - pixel(x0, y0, color); - x0 += dx_sym; - if (di<0) { - di += dy_x2; - } else { - di += dy_x2 - dx_x2; - y0 += dy_sym; - } - } - pixel(x0, y0, color); - } else { - di = dx_x2 - dy; - while (y0 != y1) { - pixel(x0, y0, color); - y0 += dy_sym; - if (di < 0) { - di += dx_x2; - } else { - di += dx_x2 - dy_x2; - x0 += dx_sym; - } - } - pixel(x0, y0, color); - } - if(auto_up) copy_to_lcd(); -} - -void C12832::hline(int x0, int y0, int x1, int colour) -{ - int x; - - /* FIXME: do this sensibly, in blocks of 8 pixels */ - for (x=x0; x<=x1; x++) { - pixel (x, y0, colour); - } if (auto_up) { copy_to_lcd (); } } -void C12832::vline(int x0, int y0, int y1, int colour) +/* Note: x1 >= x0 */ +void C12832::hline (int x0, int y0, int x1, int colour) { - int y; + int x; + int yoff; + uint8_t ybit; + + if (((x0 < 0) && (x1 < 0)) || ((x0 >= 128) && (x1 >= 128)) || (y0 < 0) || (y0 >= 32)) { + return; /* completely outside */ + } + if (x0 < 0) { + x0 = 0; + } else if (x1 >= 128) { + x1 = 127; + } + + yoff = ((y0 >> 3) << 7); + ybit = (1 << (y0 & 0x07)); - /* FIXME: do this sensibly, computing the bit positioning once */ - for (y=y0; y<=y1; y++) { - pixel (x0, y, colour); + if (draw_mode == NORMAL) { + if (colour == 0) { + for (x=x0; x<=x1; x++) { + buffer[x + yoff] &= ~ybit; // erase pixel + } + } else { + for (x=x0; x<=x1; x++) { + buffer[x + yoff] |= ybit; // set pixel + } + } + } else { // XOR mode + if (colour == 1) { + for (x=x0; x<=x1; x++) { + buffer[x + yoff] ^= ybit; // xor pixel + } + } + } + + if (auto_up) { + copy_to_lcd (); + } +} + +/* Note: y1 >= y0 */ +void C12832::vline (int x0, int y0, int y1, int colour) +{ + if (((y0 < 0) && (y1 < 0)) || ((y0 >= 32) && (y1 >= 32)) || (x0 < 0) || (x0 >= 128)) { + return; /* completely outside */ + } + if (y0 < 0) { + y0 = 0; + } else if (y1 >= 32) { + y1 = 31; } + + if ((y0 & ~0x07) == (y1 & ~0x07)) { + /* first and last pixels are in the same byte */ + uint8_t ybits = ((1 << ((y1 & 0x07) + 1)) - 1) ^ ((1 << (y0 & 0x07)) - 1); + int yoff = (y0 >> 3) << 7; /* same as y1 */ + + if (draw_mode == NORMAL) { + if (colour == 1) { + buffer[x0 + yoff] |= ybits; + } else { + buffer[x0 + yoff] &= ~ybits; + } + } else { /* XOR mode */ + buffer[x0 + yoff] ^= ybits; + } + } else { + uint8_t st_ybits = (0xff << (y0 & 0x07)); + uint8_t sp_ybits = ((1 << ((y1 & 0x07) + 1)) - 1); + int st_yoff = (y0 >> 3) << 7; + int sp_yoff = (y1 >> 3) << 7; + + /* fill in first byte */ + if (draw_mode == NORMAL) { + if (colour == 1) { + buffer[x0 + st_yoff] |= st_ybits; + } else { + buffer[x0 + st_yoff] &= ~st_ybits; + } + } else { /* XOR mode */ + buffer[x0 + st_yoff] ^= st_ybits; + } + for (st_yoff += 128; st_yoff < sp_yoff; st_yoff += 128) { + /* intervening bytes 0xff */ + if (draw_mode == NORMAL) { + if (colour == 1) { + buffer[x0 + st_yoff] = 0xff; + } else { + buffer[x0 + st_yoff] = 0x00; + } + } else { /* XOR mode */ + buffer[x0 + st_yoff] ^= 0xff; + } + } + /* and the last byte */ + if (draw_mode == NORMAL) { + if (colour == 1) { + buffer[x0 + sp_yoff] |= sp_ybits; + } else { + buffer[x0 + sp_yoff] &= ~sp_ybits; + } + } else { /* XOR mode */ + buffer[x0 + sp_yoff] ^= sp_ybits; + } + } + if (auto_up) { copy_to_lcd (); }