Sharp Memory LCD library
Dependencies: Fonts Images BurstSPI
SharpLCD.cpp
- Committer:
- star297
- Date:
- 2015-08-25
- Revision:
- 1:1bd2b42b305d
- Parent:
- 0:0a76610c48a1
File content as of revision 1:1bd2b42b305d:
#include "mbed.h" #include "SharpLCD.h" const unsigned char FONT8x8[97][8] = { {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, num_bytes_per_char {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space 0x20 {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // ! {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // " {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $ {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // % {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // & {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // ' {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / (forward slash) {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 0x30 {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1 {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2 {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4 {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5 {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6 {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7 {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9 {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // < {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // > {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ 0x40 {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P 0x50 {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // \ (back slash) {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` 0x60 {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}}; // DEL // SharpLCD commands #define SharpLCD_CMD_UPDATE (0x01) #define SharpLCD_CMD_ALL_CLEAR (0x04) // Macro to switch endianness on char value #define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7)) SharpLCD::SharpLCD(PinName mosi, PinName miso, PinName sclk, PinName chipSelect, PinName enable, PinName extcom) : spi(mosi, miso, sclk), chipSelect(chipSelect), Enable(enable), ExtCom(extcom) { //Initialize spi.frequency(3500000);// Nominal speed is 1MHz, tested working at 3MHz lcdPolarity = 0; rowCount = 0; memset((uint8_t*)pixelBuffer, White, sizeof(pixelBuffer)); // init full pixel buffer to White memset((void*)RowState, 0, sizeof(RowState)); // init row status // current pixel location _x = 0; _y = 0; // window settings _x1 = 0; _x2 = 0; _y1 = 0; _y2 = 0; _row = 0; _column = 0; } // Call this function at 55 ~ 65 Hz to keep the display up-to-date. void SharpLCD::toggle() { ExtCom=!ExtCom; } void SharpLCD::enableDisplay(void) { Enable = 1; } void SharpLCD::disableDisplay(void) { Enable = 0; } void SharpLCD::clearImmediate() { // Clear out the pixel buffer memset((void*)pixelBuffer, foreground, sizeof(pixelBuffer)); memset((void*)RowState, 0, sizeof(RowState)); chipSelect = 1; // send clear command to display cmd[0] = (uint8_t)(SWAP8(SharpLCD_CMD_ALL_CLEAR | lcdPolarity)); cmd[1] = 0; spi.fastWrite(cmd[0]); spi.fastWrite(cmd[1]); spi.clearRX(); chipSelect = 0; } void SharpLCD::update() { //Initialize the command vector cmd[0] = (uint8_t)SWAP8(SharpLCD_CMD_UPDATE); cmd[1] = SWAP8(1); chipSelect=1; rowCount = 0; display_write(); } void SharpLCD::display_write() { while(rowCount < DISPLAY_HEIGHT) { // Determine the next line to send if((RowState[rowCount / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (rowCount % DISPLAY_BUFFER_TYPE_SIZE))) != 0) { // Row has pixel changes, send this row to the display cmd[1] = (uint8_t)SWAP8(rowCount+1); memcpy(&(cmd[2]), (const void*)&(pixelBuffer[rowCount*(DISPLAY_WIDTH/DISPLAY_BUFFER_TYPE_SIZE)]), DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE)); int len=sizeof(cmd); for(int i=0; i<len; i++) { spi.fastWrite(cmd[i]); } // update pixel change status of this line as sent RowState[rowCount / DISPLAY_BUFFER_TYPE_SIZE] &= ~(1 << (rowCount % DISPLAY_BUFFER_TYPE_SIZE)); } rowCount++; } // send end of transfer bytes spi.fastWrite(cmd[0]); spi.fastWrite(0xFF); // clear SPI RX buffer spi.clearRX(); chipSelect = 0; } void SharpLCD::pixel(int x, int y, int colour) { uint8_t swapx = 7 - ((unsigned int)x & 0x07); x = ((unsigned int)x & 0xFFFFFFF8) | swapx; // determine if row has pixel changes bool change = ((pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (x % DISPLAY_BUFFER_TYPE_SIZE))) != ((colour & 0x01) << (x % DISPLAY_BUFFER_TYPE_SIZE))); if(change) { // xor operation pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] ^= (1 << (x % DISPLAY_BUFFER_TYPE_SIZE)); // update pixel change status of this line RowState[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y % DISPLAY_BUFFER_TYPE_SIZE)); } } int SharpLCD::_putc(int value) { if(value == '\n') { _column = 0; _row++; if(_row >= rows()) { _row = 0; } } else { character(_column, _row, value); _column++; if(_column >= columns()) { _column = 0; _row++; if(_row >= rows()) { _row = 0; } } } return value; } void SharpLCD::set_font(const unsigned char * f) { font = f; if (font==NULL){externalfont=0;} // set display.font else{externalfont=1;} } void SharpLCD::locate(int column, int row) { _column = column; _row = row; char_x = column; char_y = row; } int SharpLCD::_getc() { return -1; } void SharpLCD::printf(const char* format, ...) { char buffer[MAX_PRINTF_CHARS + 1] = { 0 }; uint32_t iterator = 0; va_list args; va_start(args, format); vsprintf(buffer, format, args); va_end(args); while((buffer[iterator] != 0) && (iterator < MAX_PRINTF_CHARS)) { _putc(buffer[iterator++]); } } void SharpLCD::character(int column, int row, int value) { if(externalfont){ // send external font unsigned int hor,vert,offset,bpl,j,i,b; const unsigned char* sign; unsigned char z,w; if ((value < 31) || (value > 127)) return; // test char range // read font parameter from start of array offset = font[0]; // bytes / char hor = font[1]; // get hor size of font vert = font[2]; // get vert size of font bpl = font[3]; // bytes per line if (char_x + hor > width()) { char_x = 0; char_y = char_y + vert; if (char_y >= height() - font[2]) { char_y = 0; } } window(char_x, char_y,hor,vert); sign = &font[((value -32) * offset) + 4]; w = sign[0]; for (j=0; j<vert; j++) { for (i=0; i<hor; i++) { z = sign[bpl * i + ((j & 0xF8) >> 3)+1]; b = 1 << (j & 0x07); if (( z & b ) == 0x00) { putp(foreground); } else { putp(background); } } } if ((w + 2) < hor) { // x offset to next char char_x += w + 2; } else char_x += hor; } // send default font using blitbit function else{ blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0])); } } void SharpLCD::window(int x, int y, int w, int h) { // current pixel location _x = x; _y = y; // window settings _x1 = x; _x2 = x + w - 1; _y1 = y; _y2 = y + h - 1; } void SharpLCD::putp(int colour) { pixel(_x, _y, colour); _x++; if(_x > _x2) { _x = _x1; _y++; if(_y > _y2) { _y = _y1; } } } void SharpLCD::rect(int x0, int y0, int x1, int y1, int color) { if (x1 > x0) hline(x0,x1,y0,color); else hline(x1,x0,y0,color); if (y1 > y0) vline(x0,y0,y1,color); else vline(x0,y1,y0,color); if (x1 > x0) hline(x0,x1,y1,color); else hline(x1,x0,y1,color); if (y1 > y0) vline(x1,y0,y1,color); else vline(x1,y1,y0,color); return; } void SharpLCD::fillrect(int x0, int y0, int w, int h, int colour) { unsigned long int index=0; if (w < 0) { x0 = x0 + w; w = -w; } if (h < 0) { y0 = y0 + h; h = -h; } window(x0,y0,w,h); int num = h*w; for( index = 0; index<num; index++ ) { putp(colour); } return; } void SharpLCD::circle(int x, int y, int r,int colour){ int ce = -r; int cx = r; int cy = 0; while(cx >= cy){ pixel(x+cx,y+cy,colour); pixel(x-cx,y-cy,colour); pixel(x-cx,y+cy,colour); pixel(x+cx,y-cy,colour); pixel(x+cy,y+cx,colour); pixel(x-cy,y+cx,colour); pixel(x-cy,y-cx,colour); pixel(x+cy,y-cx,colour); ce += 2*cy++ + 1; if(ce >= 0){ ce -= 2*cx---1; } } } void SharpLCD::ellipse(int xc, int yc, int a, int b, unsigned int colour) { int x = 0, y = b; long a2 = (long)a*a, b2 = (long)b*b; long crit1 = -(a2/4 + a%2 + b2); long crit2 = -(b2/4 + b%2 + a2); long crit3 = -(b2/4 + b%2); long t = -a2*y; long dxt = 2*b2*x, dyt = -2*a2*y; long d2xt = 2*b2, d2yt = 2*a2; while (y>=0 && x<=a) { pixel(xc+x, yc+y, colour); if (x!=0 || y!=0) pixel(xc-x, yc-y, colour); if (x!=0 && y!=0) { pixel(xc+x, yc-y, colour); pixel(xc-x, yc+y, colour); } if (t + b2*x <= crit1 || t + a2*y <= crit3) incx(); else if (t - a2*y > crit2) incy(); else { incx(); incy(); } } } void SharpLCD::fillellipse(int xc, int yc, int a, int b, unsigned int colour) { int x = 0, y = b; int rx = x, ry = y; unsigned int width = 1; unsigned int height = 1; long a2 = (long)a*a, b2 = (long)b*b; long crit1 = -(a2/4 + a%2 + b2); long crit2 = -(b2/4 + b%2 + a2); long crit3 = -(b2/4 + b%2); long t = -a2*y; long dxt = 2*b2*x, dyt = -2*a2*y; long d2xt = 2*b2, d2yt = 2*a2; if (b == 0) { fillrect(xc-a, yc, 2*a+1, 1, colour); return; } while (y>=0 && x<=a) { if (t + b2*x <= crit1 || t + a2*y <= crit3) { if (height == 1) ; else if (ry*2+1 > (height-1)*2) { fillrect(xc-rx, yc-ry, width, height-1, colour); fillrect(xc-rx, yc+ry+1, width, 1-height, colour); ry -= height-1; height = 1; } else { fillrect(xc-rx, yc-ry, width, ry*2+1, colour); ry -= ry; height = 1; } incx(); rx++; width += 2; } else if (t - a2*y > crit2) { incy(); height++; } else { if (ry*2+1 > height*2) { fillrect(xc-rx, yc-ry, width, height, colour); fillrect(xc-rx, yc+ry+1, width, -height, colour); } else { fillrect(xc-rx, yc-ry, width, ry*2+1, colour); } incx(); incy(); rx++; width += 2; ry -= height; height = 1; } } if (ry > height) { fillrect(xc-rx, yc-ry, width, height, colour); fillrect(xc-rx, yc+ry+1, width, -height, colour); } else { fillrect(xc-rx, yc-ry, width, ry*2+1, colour); } } void SharpLCD::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; dx = x1-x0; dy = y1-y0; if (dx == 0) { if (y1 > y0) vline(x0,y0,y1,colour); else vline(x0,y1,y0,colour); return; } if (dx > 0) { dx_sym = 1; } else { dx_sym = -1; } if (dy == 0) { if (x1 > x0) hline(x0,x1,y0,colour); else hline(x1,x0,y0,colour); return; } if (dy > 0) { dy_sym = 1; } else { dy_sym = -1; } 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, colour); x0 += dx_sym; if (di<0) { di += dy_x2; } else { di += dy_x2 - dx_x2; y0 += dy_sym; } } pixel(x0, y0, colour); } else { di = dx_x2 - dy; while (y0 != y1) { pixel(x0, y0, colour); y0 += dy_sym; if (di < 0) { di += dx_x2; } else { di += dx_x2 - dy_x2; x0 += dx_sym; } } pixel(x0, y0, colour); } return; } void SharpLCD::hline(int x0, int x1, int y, int colour) { int w; w = x1 - x0 + 1; window(x0,y,w,1); for (int x=0; x<w; x++) { putp(colour); } return; } void SharpLCD::vline(int x, int y0, int y1, int colour) { int h; h = y1 - y0 + 1; window(x,y0,1,h); for (int y=0; y<h; y++) { putp(colour); } return; } void SharpLCD::blit(int x, int y, int w, int h, const int *colour) { window(x, y, w, h); for(int i=0; i<w*h; i++) { putp(colour[i]); } } void SharpLCD::blitbit(int x, int y, int w, int h, const char* colour) { window(x, y, w, h); for(int i = 0; i < w*h; i++) { char byte = colour[i >> 3]; int offset = i & 0x7; int c = ((byte << (offset)) & 0x80) ? background : foreground; putp(c); } } int SharpLCD::columns() { return width() / 8; } int SharpLCD::rows() { return height() / 8; } int SharpLCD::width() { return DISPLAY_WIDTH; } int SharpLCD::height() { return DISPLAY_HEIGHT; } void SharpLCD::showBMP(const uint8_t* bitmap, const uint32_t bmpWidth, const uint32_t bmpHeight, const uint32_t startX, const uint32_t startY) { uint32_t bitmapLine = 0, y = startY, bytesPerLine = ((bmpWidth >= (DISPLAY_WIDTH - startX)) ? (DISPLAY_WIDTH - startX) : bmpWidth) / 8; // Apply constraints if((bmpWidth & 0x07) != 0) return; if(startX >= DISPLAY_WIDTH) return; // Copy over bytes to pixel buffer for(; y < startY + bmpHeight; y++) { memcpy( (void*) &(((uint8_t*)pixelBuffer)[((y * DISPLAY_WIDTH) + startX) / 8]), (const void*) &(bitmap[bitmapLine * (bmpWidth / 8)]), bytesPerLine); RowState[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y % DISPLAY_BUFFER_TYPE_SIZE)); bitmapLine++; } return; }