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:   Brew

Committer:
Geremia
Date:
Mon Mar 23 14:08:04 2015 +0000
Revision:
20:14daa48ffd4c
Parent:
18:ffa58f1a680a
Child:
21:ae0a4eedfc90
Add  ILI 9320/9325/9328 custom TFT932x class, parallel/spi 8/16bit, with orientation, scroll, pixelread, fastwindow.; Par8 and 16 tested, SPI not at all, needs checking if the CS toggle is necessary (see SPI8.cpp SPI16.cpp).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Geremia 4:12ba0ecc2c1f 1 /* mbed UniGraphic library - universal LCD driver class
Geremia 4:12ba0ecc2c1f 2 * Copyright (c) 2015 Giuliano Dianda
Geremia 4:12ba0ecc2c1f 3 * Released under the MIT License: http://mbed.org/license/mit
Geremia 4:12ba0ecc2c1f 4 *
Geremia 4:12ba0ecc2c1f 5 * Derived work of:
Geremia 4:12ba0ecc2c1f 6 *
Geremia 4:12ba0ecc2c1f 7 * mbed library for the mbed Lab Board 128*32 pixel LCD
Geremia 3:48f3282c2be8 8 * use C12832 controller
Geremia 3:48f3282c2be8 9 * Copyright (c) 2012 Peter Drescher - DC2PD
Geremia 3:48f3282c2be8 10 * Released under the MIT License: http://mbed.org/license/mit
Geremia 3:48f3282c2be8 11 *
Geremia 3:48f3282c2be8 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Geremia 3:48f3282c2be8 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Geremia 3:48f3282c2be8 14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Geremia 3:48f3282c2be8 15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Geremia 3:48f3282c2be8 16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Geremia 3:48f3282c2be8 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Geremia 3:48f3282c2be8 18 * THE SOFTWARE.
Geremia 3:48f3282c2be8 19 */
Geremia 3:48f3282c2be8 20
Geremia 0:75ec1b3cde17 21 #include "LCD.h"
Geremia 0:75ec1b3cde17 22
Geremia 0:75ec1b3cde17 23 //#include "mbed_debug.h"
Geremia 7:bb0383b91104 24
Geremia 0:75ec1b3cde17 25 #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; }
Geremia 2:713844a55c4e 26
Geremia 0:75ec1b3cde17 27
Geremia 0:75ec1b3cde17 28 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)
Geremia 7:bb0383b91104 29 : 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)
Geremia 0:75ec1b3cde17 30 {
Geremia 0:75ec1b3cde17 31 if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD);
Geremia 1:ff019d22b275 32 useNOP=false;
Geremia 7:bb0383b91104 33 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
Geremia 1:ff019d22b275 34 buffer16 = (unsigned short*)buffer;
Geremia 0:75ec1b3cde17 35 draw_mode = NORMAL;
Geremia 0:75ec1b3cde17 36 set_orientation(1);
Geremia 4:12ba0ecc2c1f 37 foreground(White);
Geremia 4:12ba0ecc2c1f 38 background(Black);
Geremia 2:713844a55c4e 39 set_auto_up(true);
Geremia 7:bb0383b91104 40 tftID=0;
Geremia 0:75ec1b3cde17 41 // cls();
Geremia 0:75ec1b3cde17 42 // locate(0,0);
Geremia 0:75ec1b3cde17 43 }
Geremia 1:ff019d22b275 44 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)
Geremia 7:bb0383b91104 45 : 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)
Geremia 0:75ec1b3cde17 46 {
Geremia 1:ff019d22b275 47 if(displayproto==SPI_8)
Geremia 1:ff019d22b275 48 {
Geremia 1:ff019d22b275 49 proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC);
Geremia 1:ff019d22b275 50 useNOP=false;
Geremia 1:ff019d22b275 51 }
Geremia 1:ff019d22b275 52 else if(displayproto==SPI_16)
Geremia 1:ff019d22b275 53 {
Geremia 1:ff019d22b275 54 proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC);
Geremia 1:ff019d22b275 55 useNOP=true;
Geremia 1:ff019d22b275 56 }
Geremia 7:bb0383b91104 57 buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
Geremia 1:ff019d22b275 58 buffer16 = (unsigned short*)buffer;
Geremia 0:75ec1b3cde17 59 draw_mode = NORMAL;
Geremia 0:75ec1b3cde17 60 // cls();
Geremia 0:75ec1b3cde17 61 set_orientation(1);
Geremia 4:12ba0ecc2c1f 62 foreground(White);
Geremia 4:12ba0ecc2c1f 63 background(Black);
Geremia 2:713844a55c4e 64 set_auto_up(true);
Geremia 7:bb0383b91104 65 tftID=0;
Geremia 0:75ec1b3cde17 66 // locate(0,0);
Geremia 1:ff019d22b275 67
Geremia 0:75ec1b3cde17 68 }
Geremia 0:75ec1b3cde17 69 LCD::~LCD()
Geremia 0:75ec1b3cde17 70 {
Geremia 0:75ec1b3cde17 71 free(buffer);
Geremia 0:75ec1b3cde17 72 }
Geremia 0:75ec1b3cde17 73
Geremia 1:ff019d22b275 74 void LCD::wr_cmd8(unsigned char cmd)
Geremia 0:75ec1b3cde17 75 {
Geremia 2:713844a55c4e 76 if(useNOP) proto->wr_cmd16(0xE300|cmd); // E3 is NOP cmd for LCD
Geremia 1:ff019d22b275 77 else proto->wr_cmd8(cmd);
Geremia 0:75ec1b3cde17 78 }
Geremia 1:ff019d22b275 79 void LCD::wr_data8(unsigned char data)
Geremia 0:75ec1b3cde17 80 {
Geremia 1:ff019d22b275 81 proto->wr_data8(data);
Geremia 1:ff019d22b275 82 }
Geremia 1:ff019d22b275 83 void LCD::wr_cmd16(unsigned short cmd)
Geremia 1:ff019d22b275 84 {
Geremia 1:ff019d22b275 85 proto->wr_cmd16(cmd);
Geremia 0:75ec1b3cde17 86 }
Geremia 4:12ba0ecc2c1f 87 void LCD::wr_gram(unsigned short data, unsigned int count)
Geremia 0:75ec1b3cde17 88 {
Geremia 4:12ba0ecc2c1f 89 proto->wr_gram(data, count);
Geremia 1:ff019d22b275 90 }
Geremia 4:12ba0ecc2c1f 91 void LCD::wr_grambuf(unsigned short* data, unsigned int lenght)
Geremia 1:ff019d22b275 92 {
Geremia 4:12ba0ecc2c1f 93 proto->wr_grambuf(data, lenght);
Geremia 0:75ec1b3cde17 94 }
Geremia 0:75ec1b3cde17 95 void LCD::hw_reset()
Geremia 0:75ec1b3cde17 96 {
Geremia 0:75ec1b3cde17 97 proto->hw_reset();
Geremia 0:75ec1b3cde17 98 }
Geremia 0:75ec1b3cde17 99 void LCD::BusEnable(bool enable)
Geremia 0:75ec1b3cde17 100 {
Geremia 0:75ec1b3cde17 101 proto->BusEnable(enable);
Geremia 0:75ec1b3cde17 102 }
Geremia 0:75ec1b3cde17 103
Geremia 0:75ec1b3cde17 104
Geremia 0:75ec1b3cde17 105
Geremia 0:75ec1b3cde17 106 // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays
Geremia 0:75ec1b3cde17 107 // for portrait views, XY swap will be done in sw in pixel() function
Geremia 0:75ec1b3cde17 108 void LCD::set_orientation(int o)
Geremia 0:75ec1b3cde17 109 {
Geremia 0:75ec1b3cde17 110 orientation = o;
Geremia 0:75ec1b3cde17 111 switch (o) {
Geremia 0:75ec1b3cde17 112 case (0):// portrait view -90°
Geremia 0:75ec1b3cde17 113 mirrorXY(Y);
Geremia 0:75ec1b3cde17 114 col_offset = 0;
Geremia 7:bb0383b91104 115 page_offset = _IC_PAGES-_LCDPAGES;
Geremia 7:bb0383b91104 116 set_width(screensize_Y);
Geremia 7:bb0383b91104 117 set_height(screensize_X);
Geremia 0:75ec1b3cde17 118 // portrait = true;
Geremia 0:75ec1b3cde17 119 break;
Geremia 0:75ec1b3cde17 120 case (1): // default, landscape view 0°
Geremia 0:75ec1b3cde17 121 mirrorXY(NONE);
Geremia 0:75ec1b3cde17 122 col_offset = 0;
Geremia 0:75ec1b3cde17 123 page_offset = 0;
Geremia 7:bb0383b91104 124 set_width(screensize_X);
Geremia 7:bb0383b91104 125 set_height(screensize_Y);
Geremia 0:75ec1b3cde17 126 // portrait = false;
Geremia 0:75ec1b3cde17 127 break;
Geremia 0:75ec1b3cde17 128 case (2):// portrait view +90°
Geremia 0:75ec1b3cde17 129 mirrorXY(X);
Geremia 7:bb0383b91104 130 col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram
Geremia 0:75ec1b3cde17 131 page_offset = 0;
Geremia 7:bb0383b91104 132 set_width(screensize_Y);
Geremia 7:bb0383b91104 133 set_height(screensize_X);
Geremia 0:75ec1b3cde17 134 // portrait = true;
Geremia 0:75ec1b3cde17 135 break;
Geremia 0:75ec1b3cde17 136 case (3):// landscape view +180°
Geremia 0:75ec1b3cde17 137 mirrorXY(XY);
Geremia 7:bb0383b91104 138 col_offset = _IC_X_SEGS-screensize_X;
Geremia 7:bb0383b91104 139 page_offset = _IC_PAGES-_LCDPAGES;
Geremia 7:bb0383b91104 140 set_width(screensize_X);
Geremia 7:bb0383b91104 141 set_height(screensize_Y);
Geremia 0:75ec1b3cde17 142 // portrait = false;
Geremia 0:75ec1b3cde17 143 break;
Geremia 0:75ec1b3cde17 144 }
Geremia 0:75ec1b3cde17 145 }
Geremia 0:75ec1b3cde17 146 void LCD::mirrorXY(mirror_t mode)
Geremia 0:75ec1b3cde17 147 {
Geremia 0:75ec1b3cde17 148 switch (mode)
Geremia 0:75ec1b3cde17 149 {
Geremia 0:75ec1b3cde17 150 case(NONE):
Geremia 1:ff019d22b275 151 // wr_cmd8(0xA0);
Geremia 1:ff019d22b275 152 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
Geremia 0:75ec1b3cde17 153 break;
Geremia 0:75ec1b3cde17 154 case(X):
Geremia 1:ff019d22b275 155 // wr_cmd8(0xA1);
Geremia 1:ff019d22b275 156 wr_cmd16(0xA1C8);
Geremia 0:75ec1b3cde17 157 break;
Geremia 0:75ec1b3cde17 158 case(Y):
Geremia 1:ff019d22b275 159 // wr_cmd8(0xA0);
Geremia 1:ff019d22b275 160 wr_cmd16(0xA0C0);
Geremia 0:75ec1b3cde17 161 break;
Geremia 0:75ec1b3cde17 162 case(XY):
Geremia 1:ff019d22b275 163 // wr_cmd8(0xA1);
Geremia 1:ff019d22b275 164 wr_cmd16(0xA1C0);
Geremia 0:75ec1b3cde17 165 break;
Geremia 0:75ec1b3cde17 166 }
Geremia 0:75ec1b3cde17 167 }
Geremia 0:75ec1b3cde17 168 void LCD::invert(unsigned char o)
Geremia 0:75ec1b3cde17 169 {
Geremia 1:ff019d22b275 170 if(o == 0) wr_cmd8(0xA6);
Geremia 1:ff019d22b275 171 else wr_cmd8(0xA7);
Geremia 0:75ec1b3cde17 172 }
Geremia 0:75ec1b3cde17 173
Geremia 0:75ec1b3cde17 174 void LCD::set_contrast(int o)
Geremia 0:75ec1b3cde17 175 {
Geremia 0:75ec1b3cde17 176 contrast = o;
Geremia 1:ff019d22b275 177 // wr_cmd8(0x81); // set volume
Geremia 1:ff019d22b275 178 wr_cmd16(0x8100|(o&0x3F));
Geremia 0:75ec1b3cde17 179 }
Geremia 2:713844a55c4e 180
Geremia 0:75ec1b3cde17 181 int LCD::get_contrast(void)
Geremia 0:75ec1b3cde17 182 {
Geremia 0:75ec1b3cde17 183 return(contrast);
Geremia 0:75ec1b3cde17 184 }
Geremia 0:75ec1b3cde17 185 void LCD::window(int x, int y, int w, int h) {
Geremia 0:75ec1b3cde17 186 // current pixel location
Geremia 0:75ec1b3cde17 187 cur_x = x;
Geremia 0:75ec1b3cde17 188 cur_y = y;
Geremia 0:75ec1b3cde17 189 // window settings
Geremia 0:75ec1b3cde17 190 win_x1 = x;
Geremia 0:75ec1b3cde17 191 win_x2 = x + w - 1;
Geremia 0:75ec1b3cde17 192 win_y1 = y;
Geremia 0:75ec1b3cde17 193 win_y2 = y + h - 1;
Geremia 0:75ec1b3cde17 194 }
Geremia 0:75ec1b3cde17 195 void LCD::window_pushpixel(unsigned short color) {
Geremia 0:75ec1b3cde17 196 pixel(cur_x, cur_y, color);
Geremia 0:75ec1b3cde17 197 cur_x++;
Geremia 0:75ec1b3cde17 198 if(cur_x > win_x2) {
Geremia 0:75ec1b3cde17 199 cur_x = win_x1;
Geremia 0:75ec1b3cde17 200 cur_y++;
Geremia 0:75ec1b3cde17 201 if(cur_y > win_y2) {
Geremia 0:75ec1b3cde17 202 cur_y = win_y1;
Geremia 0:75ec1b3cde17 203 }
Geremia 0:75ec1b3cde17 204 }
Geremia 0:75ec1b3cde17 205 }
Geremia 2:713844a55c4e 206 void LCD::window_pushpixel(unsigned short color, unsigned int count) {
Geremia 2:713844a55c4e 207 while(count)
Geremia 2:713844a55c4e 208 {
Geremia 2:713844a55c4e 209 pixel(cur_x, cur_y, color);
Geremia 2:713844a55c4e 210 cur_x++;
Geremia 2:713844a55c4e 211 if(cur_x > win_x2)
Geremia 2:713844a55c4e 212 {
Geremia 2:713844a55c4e 213 cur_x = win_x1;
Geremia 2:713844a55c4e 214 cur_y++;
Geremia 2:713844a55c4e 215 if(cur_y > win_y2)
Geremia 2:713844a55c4e 216 {
Geremia 2:713844a55c4e 217 cur_y = win_y1;
Geremia 2:713844a55c4e 218 }
Geremia 2:713844a55c4e 219 }
Geremia 2:713844a55c4e 220 count--;
Geremia 2:713844a55c4e 221 }
Geremia 2:713844a55c4e 222 }
Geremia 2:713844a55c4e 223 void LCD::window_pushpixelbuf(unsigned short* color, unsigned int lenght) {
Geremia 2:713844a55c4e 224 while(lenght)
Geremia 2:713844a55c4e 225 {
Geremia 2:713844a55c4e 226 pixel(cur_x, cur_y, *color++);
Geremia 2:713844a55c4e 227 cur_x++;
Geremia 2:713844a55c4e 228 if(cur_x > win_x2)
Geremia 2:713844a55c4e 229 {
Geremia 2:713844a55c4e 230 cur_x = win_x1;
Geremia 2:713844a55c4e 231 cur_y++;
Geremia 2:713844a55c4e 232 if(cur_y > win_y2)
Geremia 2:713844a55c4e 233 {
Geremia 2:713844a55c4e 234 cur_y = win_y1;
Geremia 2:713844a55c4e 235 }
Geremia 2:713844a55c4e 236 }
Geremia 2:713844a55c4e 237 lenght--;
Geremia 2:713844a55c4e 238 }
Geremia 2:713844a55c4e 239 }
Geremia 0:75ec1b3cde17 240 void LCD::pixel(int x, int y, unsigned short color)
Geremia 0:75ec1b3cde17 241 {
Geremia 0:75ec1b3cde17 242 if(!(orientation&1)) SWAP(x,y);
Geremia 0:75ec1b3cde17 243 // first check parameter
Geremia 7:bb0383b91104 244 if((x >= screensize_X) || (y >= screensize_Y)) return;
Geremia 0:75ec1b3cde17 245
Geremia 20:14daa48ffd4c 246 if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7)); // erase pixel
Geremia 20:14daa48ffd4c 247 else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7)); //Black=0000, set pixel
Geremia 20:14daa48ffd4c 248 }
Geremia 20:14daa48ffd4c 249 unsigned short LCD::pixelread(int x, int y)
Geremia 20:14daa48ffd4c 250 {
Geremia 20:14daa48ffd4c 251 if(!(orientation&1)) SWAP(x,y);
Geremia 20:14daa48ffd4c 252 // first check parameter
Geremia 20:14daa48ffd4c 253 if((x >= screensize_X) || (y >= screensize_Y)) return 0;
Geremia 20:14daa48ffd4c 254
Geremia 20:14daa48ffd4c 255 if((buffer[(x + ((y>>3)*screensize_X))^1] & (1 << (y&7)))==0) return 0xFFFF ; // pixel not set, White
Geremia 20:14daa48ffd4c 256 else return 0; // pixel set, Black
Geremia 0:75ec1b3cde17 257 }
Geremia 0:75ec1b3cde17 258 void LCD::copy_to_lcd(void)
Geremia 0:75ec1b3cde17 259 {
Geremia 0:75ec1b3cde17 260 unsigned short i=0;
Geremia 1:ff019d22b275 261 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
Geremia 7:bb0383b91104 262 for(int page=0; page<_LCDPAGES; page++)
Geremia 0:75ec1b3cde17 263 {
Geremia 1:ff019d22b275 264 // wr_cmd8(col_offset&0xF); // set column low nibble
Geremia 1:ff019d22b275 265 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble
Geremia 1:ff019d22b275 266 wr_cmd16(setcolcmd);
Geremia 1:ff019d22b275 267 wr_cmd8(0xB0|(page+page_offset)); // set page
Geremia 7:bb0383b91104 268 wr_grambuf(buffer16+i, screensize_X>>1); // send whole page pixels
Geremia 7:bb0383b91104 269 i+=screensize_X>>1;
Geremia 0:75ec1b3cde17 270 }
Geremia 0:75ec1b3cde17 271 }
Geremia 0:75ec1b3cde17 272 void LCD::cls(void)
Geremia 0:75ec1b3cde17 273 {
Geremia 4:12ba0ecc2c1f 274 unsigned short tmp = _background^0xFFFF;
Geremia 7:bb0383b91104 275 memset(buffer,tmp,screensize_X*_LCDPAGES); // clear display buffer
Geremia 1:ff019d22b275 276 unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
Geremia 7:bb0383b91104 277 for(int page=0; page<_LCDPAGES; page++)
Geremia 0:75ec1b3cde17 278 {
Geremia 1:ff019d22b275 279 // wr_cmd8((unsigned char)col_offset&0xF); // set column low nibble
Geremia 1:ff019d22b275 280 // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble
Geremia 1:ff019d22b275 281 wr_cmd16(setcolcmd);
Geremia 1:ff019d22b275 282 wr_cmd8(0xB0|(page+page_offset)); // set page
Geremia 18:ffa58f1a680a 283 wr_gram(tmp, screensize_X>>1); // send whole page pixels = background
Geremia 0:75ec1b3cde17 284 }
Geremia 7:bb0383b91104 285 }
Geremia 7:bb0383b91104 286 int LCD::sizeX()
Geremia 7:bb0383b91104 287 {
Geremia 7:bb0383b91104 288 return screensize_X;
Geremia 7:bb0383b91104 289 }
Geremia 7:bb0383b91104 290 int LCD::sizeY()
Geremia 7:bb0383b91104 291 {
Geremia 7:bb0383b91104 292 return screensize_Y;
Geremia 0:75ec1b3cde17 293 }