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.
Dependents: testUniGraphic_150217 maze_TFT_MMA8451Q TFT_test_frdm-kl25z TFT_test_NUCLEO-F411RE ... more
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 #include "platform.h" 00021 #include "LCD.h" 00022 00023 #if DEVICE_PORTINOUT 00024 #include "PAR8.h" 00025 #include "PAR16.h" 00026 #endif 00027 00028 //#include "mbed_debug.h" 00029 00030 #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } 00031 00032 #if DEVICE_PORTINOUT 00033 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) 00034 : 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) 00035 { 00036 if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); 00037 useNOP=false; 00038 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00039 buffer16 = (unsigned short*)buffer; 00040 draw_mode = NORMAL; 00041 set_orientation(1); 00042 foreground(White); 00043 background(Black); 00044 set_auto_up(true); 00045 tftID=0; 00046 // cls(); 00047 // locate(0,0); 00048 } 00049 #endif 00050 00051 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) 00052 : 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) 00053 { 00054 if(displayproto==BUS_8) 00055 { 00056 PinName pins[16]; 00057 for(int i=0; i<16; i++) pins[i]=NC; 00058 for(int i=0; i<8; i++) pins[i]=buspins[i]; 00059 proto = new BUS8(pins, CS, reset, DC, WR, RD); 00060 } 00061 useNOP=false; 00062 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00063 buffer16 = (unsigned short*)buffer; 00064 draw_mode = NORMAL; 00065 set_orientation(1); 00066 foreground(White); 00067 background(Black); 00068 set_auto_up(true); 00069 tftID=0; 00070 // cls(); 00071 // locate(0,0); 00072 } 00073 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) 00074 : 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) 00075 { 00076 if(displayproto==SPI_8) 00077 { 00078 proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC); 00079 useNOP=false; 00080 } 00081 else if(displayproto==SPI_16) 00082 { 00083 proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC); 00084 useNOP=true; 00085 } 00086 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00087 buffer16 = (unsigned short*)buffer; 00088 draw_mode = NORMAL; 00089 // cls(); 00090 set_orientation(1); 00091 foreground(White); 00092 background(Black); 00093 set_auto_up(true); 00094 tftID=0; 00095 // locate(0,0); 00096 00097 } 00098 LCD::LCD(proto_t displayproto, int Hz, int address, PinName sda, PinName scl, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char* name) 00099 : 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) 00100 { 00101 if(displayproto==I2C_){ 00102 proto = new I2C_bus(Hz,address,sda,scl); 00103 useNOP=false; 00104 } 00105 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); 00106 buffer16 = (unsigned short*)buffer; 00107 draw_mode = NORMAL; 00108 // cls(); 00109 set_orientation(1); 00110 foreground(White); 00111 background(Black); 00112 set_auto_up(true); 00113 tftID=0; 00114 } 00115 00116 LCD::~LCD() 00117 { 00118 free(buffer); 00119 } 00120 00121 void LCD::wr_cmd8(unsigned char cmd) 00122 { 00123 if(useNOP) proto->wr_cmd16(0xE300|cmd); // E3 is NOP cmd for LCD 00124 else proto->wr_cmd8(cmd); 00125 } 00126 void LCD::wr_data8(unsigned char data) 00127 { 00128 proto->wr_data8(data); 00129 } 00130 void LCD::wr_cmd16(unsigned short cmd) 00131 { 00132 proto->wr_cmd16(cmd); 00133 } 00134 void LCD::wr_gram(unsigned short data, unsigned int count) 00135 { 00136 proto->wr_gram(data, count); 00137 } 00138 void LCD::wr_grambuf(unsigned short* data, unsigned int lenght) 00139 { 00140 proto->wr_grambuf(data, lenght); 00141 } 00142 void LCD::hw_reset() 00143 { 00144 proto->hw_reset(); 00145 } 00146 void LCD::BusEnable(bool enable) 00147 { 00148 proto->BusEnable(enable); 00149 } 00150 00151 00152 00153 // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays 00154 // for portrait views, XY swap will be done in sw in pixel() function 00155 void LCD::set_orientation(int o) 00156 { 00157 orientation = o; 00158 switch (o) { 00159 case (0):// portrait view -90° 00160 mirrorXY(Y); 00161 col_offset = 0; 00162 page_offset = _IC_PAGES-_LCDPAGES; 00163 set_width(screensize_Y); 00164 set_height(screensize_X); 00165 // portrait = true; 00166 break; 00167 case (1): // default, landscape view 0° 00168 mirrorXY(NONE); 00169 col_offset = 0; 00170 page_offset = 0; 00171 set_width(screensize_X); 00172 set_height(screensize_Y); 00173 // portrait = false; 00174 break; 00175 case (2):// portrait view +90° 00176 mirrorXY(X); 00177 col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram 00178 page_offset = 0; 00179 set_width(screensize_Y); 00180 set_height(screensize_X); 00181 // portrait = true; 00182 break; 00183 case (3):// landscape view +180° 00184 mirrorXY(XY); 00185 col_offset = _IC_X_SEGS-screensize_X; 00186 page_offset = _IC_PAGES-_LCDPAGES; 00187 set_width(screensize_X); 00188 set_height(screensize_Y); 00189 // portrait = false; 00190 break; 00191 } 00192 } 00193 void LCD::mirrorXY(mirror_t mode) 00194 { 00195 switch (mode) 00196 { 00197 case(NONE): 00198 // wr_cmd8(0xA0); 00199 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 00200 break; 00201 case(X): 00202 // wr_cmd8(0xA1); 00203 wr_cmd16(0xA1C8); 00204 break; 00205 case(Y): 00206 // wr_cmd8(0xA0); 00207 wr_cmd16(0xA0C0); 00208 break; 00209 case(XY): 00210 // wr_cmd8(0xA1); 00211 wr_cmd16(0xA1C0); 00212 break; 00213 } 00214 } 00215 void LCD::invert(unsigned char o) 00216 { 00217 if(o == 0) wr_cmd8(0xA6); 00218 else wr_cmd8(0xA7); 00219 } 00220 00221 void LCD::set_contrast(int o) 00222 { 00223 contrast = o; 00224 // wr_cmd8(0x81); // set volume 00225 wr_cmd16(0x8100|(o&0x3F)); 00226 } 00227 00228 int LCD::get_contrast(void) 00229 { 00230 return(contrast); 00231 } 00232 void LCD::window(int x, int y, int w, int h) { 00233 // current pixel location 00234 cur_x = x; 00235 cur_y = y; 00236 // window settings 00237 win_x1 = x; 00238 win_x2 = x + w - 1; 00239 win_y1 = y; 00240 win_y2 = y + h - 1; 00241 } 00242 void LCD::window_pushpixel(unsigned short color) { 00243 pixel(cur_x, cur_y, color); 00244 cur_x++; 00245 if(cur_x > win_x2) { 00246 cur_x = win_x1; 00247 cur_y++; 00248 if(cur_y > win_y2) { 00249 cur_y = win_y1; 00250 } 00251 } 00252 } 00253 void LCD::window_pushpixel(unsigned short color, unsigned int count) { 00254 while(count) 00255 { 00256 pixel(cur_x, cur_y, color); 00257 cur_x++; 00258 if(cur_x > win_x2) 00259 { 00260 cur_x = win_x1; 00261 cur_y++; 00262 if(cur_y > win_y2) 00263 { 00264 cur_y = win_y1; 00265 } 00266 } 00267 count--; 00268 } 00269 } 00270 void LCD::window_pushpixelbuf(unsigned short* color, unsigned int lenght) { 00271 while(lenght) 00272 { 00273 pixel(cur_x, cur_y, *color++); 00274 cur_x++; 00275 if(cur_x > win_x2) 00276 { 00277 cur_x = win_x1; 00278 cur_y++; 00279 if(cur_y > win_y2) 00280 { 00281 cur_y = win_y1; 00282 } 00283 } 00284 lenght--; 00285 } 00286 } 00287 void LCD::pixel(int x, int y, unsigned short color) 00288 { 00289 if(!(orientation&1)) SWAP(x,y); 00290 // first check parameter 00291 if((x >= screensize_X) || (y >= screensize_Y)) return; 00292 00293 if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7)); // erase pixel 00294 else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7)); //Black=0000, set pixel 00295 } 00296 unsigned short LCD::pixelread(int x, int y) 00297 { 00298 if(!(orientation&1)) SWAP(x,y); 00299 // first check parameter 00300 if((x >= screensize_X) || (y >= screensize_Y)) return 0; 00301 00302 if((buffer[(x + ((y>>3)*screensize_X))^1] & (1 << (y&7)))==0) return 0xFFFF ; // pixel not set, White 00303 else return 0; // pixel set, Black 00304 } 00305 void LCD::copy_to_lcd(void) 00306 { 00307 unsigned short i=0; 00308 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); 00309 for(int page=0; page<_LCDPAGES; page++) 00310 { 00311 // wr_cmd8(col_offset&0xF); // set column low nibble 00312 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble 00313 wr_cmd16(setcolcmd); 00314 wr_cmd8(0xB0|(page+page_offset)); // set page 00315 wr_grambuf(buffer16+i, screensize_X>>1); // send whole page pixels 00316 i+=screensize_X>>1; 00317 } 00318 } 00319 void LCD::cls(void) 00320 { 00321 unsigned short tmp = _background^0xFFFF; 00322 memset(buffer,tmp,screensize_X*_LCDPAGES); // clear display buffer 00323 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); 00324 for(int page=0; page<_LCDPAGES; page++) 00325 { 00326 // wr_cmd8((unsigned char)col_offset&0xF); // set column low nibble 00327 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble 00328 wr_cmd16(setcolcmd); 00329 wr_cmd8(0xB0|(page+page_offset)); // set page 00330 wr_gram(tmp, screensize_X>>1); // send whole page pixels = background 00331 } 00332 } 00333 int LCD::sizeX() 00334 { 00335 return screensize_X; 00336 } 00337 int LCD::sizeY() 00338 { 00339 return screensize_Y; 00340 }
Generated on Tue Jul 12 2022 13:49:07 by 1.7.2