Simple library for UC1701 based GLCD's
Dependents: Opensmart_LCD_UC1701
With lots of fonts! Will include more in the future. A couple bitmaps have also been added.
UC1701.cpp
- Committer:
- Anaesthetix
- Date:
- 2016-12-19
- Revision:
- 5:7494bdca926b
- Parent:
- 4:8da4c691643a
File content as of revision 5:7494bdca926b:
/** * This is a simple library for UC1701 controlled graphic LCD's. * Written for a cheap OPEN-SMART 1.8" 128x64 display * See http://www.dx.com/p/open-smart-1-8-128-64-lcd-display-breakout-module-w-blue-backlit-444694 * * Written by: Erik van de Coevering * With thanks to Tim Barr from whom I've reused some code * Use this code in whatever way you like, as long as it stays free of charge! */ #include "UC1701.h" UC1701::UC1701(SPI &lcd, DigitalOut &lcd_cs, DigitalOut &lcd_cd) { _lcd = &lcd; _lcd_cs = &lcd_cs; _lcd_cd = &lcd_cd; } void UC1701::init() { _lcd_cs->write(1); _lcd->frequency(24000000); // Abusing SPI to save some time.. _lcd->format(8,3); _lcd_cs->write(0); // enable SPI _lcd_cd->write(0); // COMMAND mode wait_ms(50); _lcd->write(0xE2); // Reset _lcd->write(0x40); // Set display start line to 0 _lcd->write(0xA1); // Set SEG direction _lcd->write(0xC0); // Set COM direction _lcd->write(0xA2); // Set bias = 1/9 _lcd->write(0x2C); // Boost ON _lcd->write(0x2E); // Voltage regulator on _lcd->write(0x2F); // Voltage follower on _lcd->write(0xF8); // Set booster ratio _lcd->write(0x00); _lcd->write(0x23); // Set resistor ratio _lcd->write(0x81); // Set contrast to _lcd->write(0x28); // 40 _lcd->write(0xEE); // Set cursor update -> after write, column cursor will be updated (rows will not!) _lcd->write(0xAC); // Disable static indicator _lcd->write(0x00); _lcd->write(0xA6); // Disable inverse _lcd->write(0xAF); // Display enable //_lcd->write(0xA5); // display all points _lcd->write(0xA4); // clear _lcd_cs->write(1); // disable SPI _lcd_cd->write(1); // DATA mode } void UC1701::setContrast(char contrast) { _lcd_cs->write(0); // enable SPI _lcd_cd->write(0); // command mode _lcd->write(0x81); // command to set contrast _lcd->write(contrast); // set contrast _lcd_cs->write(1); _lcd_cd->write(1); } void UC1701::setCursor(char column, char line) { int i, j; column = column+4; i=(column&0xF0)>>4; j=column&0x0F; _lcd_cd->write(0); _lcd->write(0xb0+line); _lcd->write(0x10+i); _lcd->write(j); _lcd_cd->write(1); } void UC1701::clear() { _lcd_cs->write(0); for(unsigned short j = 0; j < 8; j++) { UC1701::setCursor(0, j); for(unsigned short i = 0; i < 128 ; i++) { _lcd->write(0x00); } } UC1701::setCursor(0, 0); _lcd_cs->write(1); } // fill() only used to optimize the library. Using command 0xA5 is faster, if needed. void UC1701::fill() { _lcd_cs->write(0); _lcd_cd->write(1); for(unsigned short j = 0; j < 8; j++) { UC1701::setCursor(0, j); for(unsigned short i = 0; i < 128 ; i++) { _lcd->write(0xFF); } } UC1701::setCursor(0, 0); _lcd_cs->write(1); } void UC1701::writeText2d(char column, char page, const char font_address[96][8], const char *text, int size) { _lcd_cs->write(0); UC1701::setCursor(column, page); for(int i=0; i<size; i++) { for(int a=0; a<8; a++) { _lcd->write((font_address[(text[i]-32)][a])); } } _lcd_cs->write(1); } void UC1701::writeText(char column, char page, const char *font_address, const char *text, const uint8_t size) { // Position of character data in memory array uint16_t pos_array; // temporary column, page address, and column_cnt are used // to stay inside display area uint8_t i,y, column_cnt = 0; uint8_t count = 0; // font information, needed for calculation uint8_t start_code, last_code, width, page_height, bytes_p_char; uint8_t *txtbuffer; start_code = font_address[2]; // get first defined character last_code = font_address[3]; // get last defined character width = font_address[4]; // width in pixel of one char page_height = font_address[6]; // page count per char bytes_p_char = font_address[7]; // bytes per char _lcd_cs->write(0); // Enable SPI _lcd_cd->write(1); // Data mode if(page_height + page > LCDPAGES) //stay inside display area page_height = LCDPAGES - page; // The string is displayed character after character. If the font has more then one page, // the top page is printed first, then the next page and so on for(y = 0; y < page_height; y++) { txtbuffer = &_lcdbuffer[page*LCDWIDTH + column]; column_cnt = 0; // clear column_cnt start point i = 0; while(( i < size) && ((column_cnt + column) < LCDWIDTH)) { if(text[i] < start_code || (uint8_t)text[i] > last_code) //make sure data is valid i++; else { // calculate position of ASCII character in font array // bytes for header + (ASCII - startcode) * bytes per char) pos_array = 8 + (uint8_t)(text[i++] - start_code) * bytes_p_char; // get the dot pattern for the part of the char to print pos_array += y*width; // stay inside display area if((column_cnt + width + column) > LCDWIDTH) column_cnt = LCDWIDTH-width; // copy character data to buffer memcpy (txtbuffer+column_cnt,font_address+pos_array,width); } column_cnt += width; } UC1701::setCursor(column,page); // set start position x and y do { _lcd->write(txtbuffer[count]); count++; } while ((count <= column_cnt)); } _lcd_cs->write(1); // Disable SPI } void UC1701::drawBitmap(const char *data) { int cnt = 0; _lcd_cs->write(0); _lcd_cd->write(1); UC1701::setCursor(0,0); for(int row=0; row<8; row++) { UC1701::setCursor(0, row); for(int column=0; column<128; column++) { _lcd->write(data[cnt]); cnt++; } } } void UC1701::drawLineHor(char posx, char posy, char height, char width) { char page, offset, offset2; char buffer[2] = {0xFF, 0xFF}; _lcd_cs->write(0); _lcd_cd->write(1); if(width+posx > LCDWIDTH) width = (LCDWIDTH-posx); // keep inside display area page = posy/8; offset = posy - (page*8); buffer[0] = buffer[0] >> (8-height); buffer[0] = buffer[0] << offset; if((offset + height) > 8) { offset2 = ((offset+height)-8); buffer[1] = buffer[1] - (0xFF << (offset2)); } UC1701::setCursor(posx, page); for(int i=0; i<width; i++) _lcd->write(buffer[0]); if(buffer[1] != 0xFF && (page+1) < 8) { // only write if line takes up > 1 page & keep inside display area UC1701::setCursor(posx, (page+1)); for(int i=0; i<width; i++) _lcd->write(buffer[1]); } _lcd_cs->write(1); } void UC1701::drawLineVert(char posx, char posy, char height, char width) { char page, pagecount, offset, offset2; _lcd_cs->write(0); _lcd_cd->write(1); page = posy/8; pagecount = height/8; offset2 = height - (pagecount*8); UC1701::setCursor(posx, page); for(int i=0; i<width; i++) _lcd->write((0xFF>>offset)); for(; pagecount > 1; pagecount--) { page++; UC1701::setCursor(posx, page); for(int i=0; i<width; i++) _lcd->write(0xFF); } UC1701::setCursor(posx, (page+1)); for(int i=0; i<width; i++) _lcd->write((0xFF<<offset2)); _lcd_cs->write(1); } void UC1701::clearBuffer(void) { for(int i=0; i<(LCDWIDTH*LCDPAGES); i++) buff[i] = 0; } void UC1701::update(void) { int cnt = 0; _lcd_cs->write(0); _lcd_cd->write(1); UC1701::setCursor(0,0); for(int row=0; row<8; row++) { UC1701::setCursor(0, row); for(int column=0; column<128; column++) { _lcd->write(buff[cnt]); cnt++; } } _lcd_cs->write(1); } void UC1701::drawbufferLineHor(char posx, char posy, char height, char width) { char page, offset, offset2; int cursor; char buffer[2] = {0xFF, 0xFF}; if(width+posx > LCDWIDTH) width = (LCDWIDTH-posx); // keep inside display area page = posy/8; offset = posy - (page*8); buffer[0] = buffer[0] >> (8-height); buffer[0] = buffer[0] << offset; if((offset + height) > 8) { offset2 = ((offset+height)-8); buffer[1] = buffer[1] - (0xFF << (offset2)); } cursor = posx + (page*128); for(int i=0; i<width; i++) UC1701::buff[cursor+i] |= buffer[0]; if(buffer[1] != 0xFF && (page+1) < 8) { // only write if line takes up > 1 page & keep inside display area for(int i=0; i<width; i++) UC1701::buff[cursor+i+128] |= buffer[1]; } } void UC1701::drawbufferLineVert(char posx, char posy, char height, char width) { char page, pagecount, offset, offset2; int cursor; page = posy/8; pagecount = height/8; offset2 = height - (pagecount*8); cursor = posx + (page*128); // LCDWIDTH for(int i=0; i<width; i++) UC1701::buff[cursor+i] |= (0xFF>>offset); for(; pagecount > 1; pagecount--) { page++; cursor += 128; for(int i=0; i<width; i++) UC1701::buff[cursor+i] |= 0xFF; } cursor += 128; for(int i=0; i<width; i++) UC1701::buff[cursor+i] |= (0xFF >> offset2); }