Basically i glued Peter Drescher and Simon Ford libs in a GraphicsDisplay class, then derived TFT or LCD class (which inherits Protocols class), then the most derived ones (Inits), which are per-display and are the only part needed to be adapted to diff hw.
Fork of UniGraphic by
LCD.cpp
00001 /* mbed UniGraphic library - universal LCD driver class 00002 * Copyright (c) 2015 Giuliano Dianda 00003 * Released under the MIT License: http://mbed.org/license/mit 00004 * 00005 * Derived work of: 00006 * 00007 * mbed library for the mbed Lab Board 128*32 pixel LCD 00008 * use C12832 controller 00009 * Copyright (c) 2012 Peter Drescher - DC2PD 00010 * Released under the MIT License: http://mbed.org/license/mit 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00013 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00014 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00015 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00016 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00018 * THE SOFTWARE. 00019 */ 00020 00021 #include "LCD.h" 00022 00023 //#include "mbed_debug.h" 00024 00025 #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } 00026 00027 00028 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) 00029 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_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) 00030 { 00031 if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); 00032 useNOP=false; 00033 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00034 buffer16 = (unsigned short*)buffer; 00035 draw_mode = NORMAL; 00036 set_orientation(1); 00037 foreground(White); 00038 background(Black); 00039 set_auto_up(true); 00040 tftID=0; 00041 // cls(); 00042 // locate(0,0); 00043 } 00044 LCD::LCD(proto_t displayproto, PinName* buspins, 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) 00045 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_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) 00046 { 00047 if(displayproto==BUS_8) 00048 { 00049 PinName pins[16]; 00050 for(int i=0; i<16; i++) pins[i]=NC; 00051 for(int i=0; i<8; i++) pins[i]=buspins[i]; 00052 proto = new BUS8(pins, CS, reset, DC, WR, RD); 00053 } 00054 useNOP=false; 00055 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00056 buffer16 = (unsigned short*)buffer; 00057 draw_mode = NORMAL; 00058 set_orientation(1); 00059 foreground(White); 00060 background(Black); 00061 set_auto_up(true); 00062 tftID=0; 00063 // cls(); 00064 // locate(0,0); 00065 } 00066 LCD::LCD(proto_t displayproto, int Hz, 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) 00067 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_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) 00068 { 00069 if(displayproto==SPI_8) 00070 { 00071 proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC); 00072 useNOP=false; 00073 } 00074 else if(displayproto==SPI_16) 00075 { 00076 proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC); 00077 useNOP=true; 00078 } 00079 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00080 buffer16 = (unsigned short*)buffer; 00081 draw_mode = NORMAL; 00082 // cls(); 00083 set_orientation(1); 00084 foreground(White); 00085 background(Black); 00086 set_auto_up(true); 00087 tftID=0; 00088 // locate(0,0); 00089 00090 } 00091 LCD::~LCD() 00092 { 00093 free(buffer); 00094 } 00095 00096 void LCD::wr_cmd8(unsigned char cmd) 00097 { 00098 if(useNOP) proto->wr_cmd16(0xE300|cmd); // E3 is NOP cmd for LCD 00099 else proto->wr_cmd8(cmd); 00100 } 00101 void LCD::wr_data8(unsigned char data) 00102 { 00103 proto->wr_data8(data); 00104 } 00105 void LCD::wr_cmd16(unsigned short cmd) 00106 { 00107 proto->wr_cmd16(cmd); 00108 } 00109 void LCD::wr_gram(unsigned short data, unsigned int count) 00110 { 00111 proto->wr_gram(data, count); 00112 } 00113 void LCD::wr_grambuf(unsigned short* data, unsigned int lenght) 00114 { 00115 proto->wr_grambuf(data, lenght); 00116 } 00117 void LCD::hw_reset() 00118 { 00119 proto->hw_reset(); 00120 } 00121 void LCD::BusEnable(bool enable) 00122 { 00123 proto->BusEnable(enable); 00124 } 00125 00126 00127 00128 // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays 00129 // for portrait views, XY swap will be done in sw in pixel() function 00130 void LCD::set_orientation(int o) 00131 { 00132 orientation = o; 00133 switch (o) { 00134 case (0):// portrait view -90° 00135 mirrorXY(Y); 00136 col_offset = 0; 00137 page_offset = _IC_PAGES-_LCDPAGES; 00138 set_width(screensize_Y); 00139 set_height(screensize_X); 00140 // portrait = true; 00141 break; 00142 case (1): // default, landscape view 0° 00143 mirrorXY(NONE); 00144 col_offset = 0; 00145 page_offset = 0; 00146 set_width(screensize_X); 00147 set_height(screensize_Y); 00148 // portrait = false; 00149 break; 00150 case (2):// portrait view +90° 00151 mirrorXY(X); 00152 col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram 00153 page_offset = 0; 00154 set_width(screensize_Y); 00155 set_height(screensize_X); 00156 // portrait = true; 00157 break; 00158 case (3):// landscape view +180° 00159 mirrorXY(XY); 00160 col_offset = _IC_X_SEGS-screensize_X; 00161 page_offset = _IC_PAGES-_LCDPAGES; 00162 set_width(screensize_X); 00163 set_height(screensize_Y); 00164 // portrait = false; 00165 break; 00166 } 00167 } 00168 void LCD::mirrorXY(mirror_t mode) 00169 { 00170 switch (mode) 00171 { 00172 case(NONE): 00173 // wr_cmd8(0xA0); 00174 wr_cmd16(0xA0C8); // this is in real Y mirror command, but seems most displays have COMs wired inverted, so assume this is the default no-y-mirror 00175 break; 00176 case(X): 00177 // wr_cmd8(0xA1); 00178 wr_cmd16(0xA1C8); 00179 break; 00180 case(Y): 00181 // wr_cmd8(0xA0); 00182 wr_cmd16(0xA0C0); 00183 break; 00184 case(XY): 00185 // wr_cmd8(0xA1); 00186 wr_cmd16(0xA1C0); 00187 break; 00188 } 00189 } 00190 void LCD::invert(unsigned char o) 00191 { 00192 if(o == 0) wr_cmd8(0xA6); 00193 else wr_cmd8(0xA7); 00194 } 00195 00196 void LCD::set_contrast(int o) 00197 { 00198 contrast = o; 00199 // wr_cmd8(0x81); // set volume 00200 wr_cmd16(0x8100|(o&0x3F)); 00201 } 00202 00203 int LCD::get_contrast(void) 00204 { 00205 return(contrast); 00206 } 00207 void LCD::window(int x, int y, int w, int h) { 00208 // current pixel location 00209 cur_x = x; 00210 cur_y = y; 00211 // window settings 00212 win_x1 = x; 00213 win_x2 = x + w - 1; 00214 win_y1 = y; 00215 win_y2 = y + h - 1; 00216 } 00217 void LCD::window_pushpixel(unsigned short color) { 00218 pixel(cur_x, cur_y, color); 00219 cur_x++; 00220 if(cur_x > win_x2) { 00221 cur_x = win_x1; 00222 cur_y++; 00223 if(cur_y > win_y2) { 00224 cur_y = win_y1; 00225 } 00226 } 00227 } 00228 void LCD::window_pushpixel(unsigned short color, unsigned int count) { 00229 while(count) 00230 { 00231 pixel(cur_x, cur_y, color); 00232 cur_x++; 00233 if(cur_x > win_x2) 00234 { 00235 cur_x = win_x1; 00236 cur_y++; 00237 if(cur_y > win_y2) 00238 { 00239 cur_y = win_y1; 00240 } 00241 } 00242 count--; 00243 } 00244 } 00245 void LCD::window_pushpixelbuf(unsigned short* color, unsigned int lenght) { 00246 while(lenght) 00247 { 00248 pixel(cur_x, cur_y, *color++); 00249 cur_x++; 00250 if(cur_x > win_x2) 00251 { 00252 cur_x = win_x1; 00253 cur_y++; 00254 if(cur_y > win_y2) 00255 { 00256 cur_y = win_y1; 00257 } 00258 } 00259 lenght--; 00260 } 00261 } 00262 void LCD::pixel(int x, int y, unsigned short color) 00263 { 00264 if(!(orientation&1)) SWAP(x,y); 00265 // first check parameter 00266 if((x >= screensize_X) || (y >= screensize_Y)) return; 00267 00268 if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7)); // erase pixel 00269 else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7)); //Black=0000, set pixel 00270 } 00271 unsigned short LCD::pixelread(int x, int y) 00272 { 00273 if(!(orientation&1)) SWAP(x,y); 00274 // first check parameter 00275 if((x >= screensize_X) || (y >= screensize_Y)) return 0; 00276 00277 if((buffer[(x + ((y>>3)*screensize_X))^1] & (1 << (y&7)))==0) return 0xFFFF ; // pixel not set, White 00278 else return 0; // pixel set, Black 00279 } 00280 void LCD::copy_to_lcd(void) 00281 { 00282 unsigned short i=0; 00283 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); 00284 for(int page=0; page<_LCDPAGES; page++) 00285 { 00286 // wr_cmd8(col_offset&0xF); // set column low nibble 00287 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble 00288 wr_cmd16(setcolcmd); 00289 wr_cmd8(0xB0|(page+page_offset)); // set page 00290 wr_grambuf(buffer16+i, screensize_X>>1); // send whole page pixels 00291 i+=screensize_X>>1; 00292 } 00293 } 00294 void LCD::cls(void) 00295 { 00296 unsigned short tmp = _background^0xFFFF; 00297 memset(buffer,tmp,screensize_X*_LCDPAGES); // clear display buffer 00298 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); 00299 for(int page=0; page<_LCDPAGES; page++) 00300 { 00301 // wr_cmd8((unsigned char)col_offset&0xF); // set column low nibble 00302 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble 00303 wr_cmd16(setcolcmd); 00304 wr_cmd8(0xB0|(page+page_offset)); // set page 00305 wr_gram(tmp, screensize_X>>1); // send whole page pixels = background 00306 } 00307 } 00308 int LCD::sizeX() 00309 { 00310 return screensize_X; 00311 } 00312 int LCD::sizeY() 00313 { 00314 return screensize_Y; 00315 }
Generated on Wed Jul 13 2022 21:19:22 by 1.7.2