UniGraphic-Fork for ST7920-LCD-controller and SH1106. Tested with 128x64 LCD with SPI and 128x64-OLED with IIC
Dependents: UniGraphic-St7920-Test AfficheurUTILECO
Fork of UniGraphic by
Fork of the UniGraphic-Library for monochrome LCDs with ST7920 controller and 128x64-IIC-OLED-Display with SH1106-Controller
Had to adapt LCD for following reasons:
- Give access to screenbuffer buffer[] to parent class
- pixel() and pixel_read() as they are hardware-dependent
- added reset-pin to IIC-Interface
GraphicDisplay:: sends buffer to LCD when auto_update is set to true.
Testprogram for ST7920 can be found here:
https://developer.mbed.org/users/charly/code/UniGraphic-St7920-Test/
Diff: Display/LCD.cpp
- Revision:
- 0:75ec1b3cde17
- Child:
- 1:ff019d22b275
diff -r 000000000000 -r 75ec1b3cde17 Display/LCD.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Display/LCD.cpp Thu Feb 12 22:22:47 2015 +0000 @@ -0,0 +1,217 @@ +#include "LCD.h" + +//#include "mbed_debug.h" +//#define LCDPAGES (LCDSIZE_Y>>3) // 8raws per page +//#define IC_PAGES (IC_Y_COMS>>3) // max pages in IC ddram, 8raws per page +#define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } +#define USEFRAMEBUFFER +//#define FRAMEBUFSIZE (LCDSIZE_X*LCDPAGES) +Protocols* proto; + +LCD::LCD(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name) + : /*PAR8(port, CS, reset, DC, WR, RD),*/ GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y), LCDPAGES(lcdsize_y>>3), IC_X_SEGS(ic_x_segs), IC_Y_COMS(ic_y_coms), IC_PAGES(ic_y_coms>>3) +{ + // LCDPAGES = LCDSIZE_Y>>3; + // IC_PAGES = IC_Y_COMS>>3; + // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; + // PAR8 par8proto(port, CS, reset, DC, WR, RD); + if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); + buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); + draw_mode = NORMAL; + set_orientation(1); + // cls(); + // locate(0,0); +} +LCD::LCD(proto_t displayproto,PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name) + : GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y), LCDPAGES(lcdsize_y>>3), IC_X_SEGS(ic_x_segs), IC_Y_COMS(ic_y_coms), IC_PAGES(ic_y_coms>>3) +{ + // LCDPAGES = LCDSIZE_Y>>3; + // IC_PAGES = IC_Y_COMS>>3; + // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; + // PAR8 par8proto(port, CS, reset, DC, WR, RD); + if(displayproto==SPI_8) proto = new SPI8(mosi, miso, sclk, CS, reset, DC); + buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); + draw_mode = NORMAL; + // cls(); + set_orientation(1); + // locate(0,0); +} +LCD::~LCD() +{ + free(buffer); +} + +void LCD::wr_cmd(unsigned char cmd) + { + proto->wr_cmd(cmd); + } +void LCD::wr_data8(unsigned char data8) + { + proto->wr_data8(data8); + } +void LCD::wr_data8(unsigned char data8, unsigned int count) + { + proto->wr_data8(data8, count); + } +void LCD::wr_data8buf(unsigned char* data8, unsigned int lenght) + { + proto->wr_data8buf(data8, lenght); + } +void LCD::hw_reset() + { + proto->hw_reset(); + } +void LCD::BusEnable(bool enable) + { + proto->BusEnable(enable); + } + + + +// monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays +// for portrait views, XY swap will be done in sw in pixel() function +void LCD::set_orientation(int o) +{ + orientation = o; + switch (o) { + case (0):// portrait view -90° + mirrorXY(Y); + col_offset = 0; + page_offset = IC_PAGES-LCDPAGES; + set_width(LCDSIZE_Y); + set_height(LCDSIZE_X); + // portrait = true; + break; + case (1): // default, landscape view 0° + mirrorXY(NONE); + col_offset = 0; + page_offset = 0; + set_width(LCDSIZE_X); + set_height(LCDSIZE_Y); + // portrait = false; + break; + case (2):// portrait view +90° + mirrorXY(X); + col_offset = IC_X_SEGS-LCDSIZE_X; // some displays have less pixels than IC ram + page_offset = 0; + set_width(LCDSIZE_Y); + set_height(LCDSIZE_X); + // portrait = true; + break; + case (3):// landscape view +180° + mirrorXY(XY); + col_offset = IC_X_SEGS-LCDSIZE_X; + page_offset = IC_PAGES-LCDPAGES; + set_width(LCDSIZE_X); + set_height(LCDSIZE_Y); + // portrait = false; + break; + } +} +void LCD::mirrorXY(mirror_t mode) +{ + switch (mode) + { + case(NONE): + wr_cmd(0xA0); + wr_cmd(0xC8); // this is in real Y mirror command, but seems most displays have COMs wired inverted, so assume this is the default no-y-mirror + break; + case(X): + wr_cmd(0xA1); + wr_cmd(0xC8); + break; + case(Y): + wr_cmd(0xA0); + wr_cmd(0xC0); + break; + case(XY): + wr_cmd(0xA1); + wr_cmd(0xC0); + break; + } +} +void LCD::invert(unsigned char o) +{ + if(o == 0) wr_cmd(0xA6); + else wr_cmd(0xA7); +} + +void LCD::set_contrast(int o) +{ + contrast = o; + wr_cmd(0x81); // set volume + wr_cmd(o & 0x3F); +} +void LCD::set_auto_up(bool up) +{ + if(up) auto_up = true; + else auto_up = false; +} +bool LCD::get_auto_up(void) +{ + return (auto_up); +} +int LCD::get_contrast(void) +{ + return(contrast); +} +void LCD::window(int x, int y, int w, int h) { + // current pixel location + cur_x = x; + cur_y = y; + // window settings + win_x1 = x; + win_x2 = x + w - 1; + win_y1 = y; + win_y2 = y + h - 1; +} +void LCD::window_pushpixel(unsigned short color) { + pixel(cur_x, cur_y, color); + cur_x++; + if(cur_x > win_x2) { + cur_x = win_x1; + cur_y++; + if(cur_y > win_y2) { + cur_y = win_y1; + } + } +} +void LCD::pixel(int x, int y, unsigned short color) +{ + if(!(orientation&1)) SWAP(x,y); + // first check parameter + if((x >= LCDSIZE_X) || (y >= LCDSIZE_Y)) return; + +// if(draw_mode == NORMAL) +// { + if(color == 0) buffer[x + ((y>>3) * LCDSIZE_X)] &= ~(1 << (y&7)); // erase pixel + else buffer[x + ((y>>3) * LCDSIZE_X)] |= (1 << (y&7)); // set pixel +// } +// else +// { // XOR mode +// if(color == 1) buffer[x + ((y>>3) * LCDSIZE_X)] ^= (1 << (y&7)); // xor pixel +// } +} +void LCD::copy_to_lcd(void) +{ + unsigned short i=0; + for(int page=0; page<LCDPAGES; page++) + { + wr_cmd((unsigned char)col_offset&0xF); // set column low nibble + wr_cmd(0x10|(col_offset>>4)); // set column hi nibble + wr_cmd(0xB0|(page+page_offset)); // set page + wr_data8buf(buffer+i, LCDSIZE_X); // send whole page pixels + i+=LCDSIZE_X; + } +} +void LCD::cls(void) +{ + memset(buffer,0x00,LCDSIZE_X*LCDPAGES); // clear display buffer + for(int page=0; page<LCDPAGES; page++) + { + wr_cmd((unsigned char)col_offset&0xF); // set column low nibble + wr_cmd(0x10|(col_offset>>4)); // set column hi nibble + wr_cmd(0xB0|(page+page_offset)); // set page + wr_data8(0, LCDSIZE_X); // send whole page pixels =0 + } +} \ No newline at end of file