.
Display/LCD.cpp@0:75ec1b3cde17, 2015-02-12 (annotated)
- Committer:
- Geremia
- Date:
- Thu Feb 12 22:22:47 2015 +0000
- Revision:
- 0:75ec1b3cde17
- Child:
- 1:ff019d22b275
Initial tests, LCD par and spi ok
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Geremia | 0:75ec1b3cde17 | 1 | #include "LCD.h" |
Geremia | 0:75ec1b3cde17 | 2 | |
Geremia | 0:75ec1b3cde17 | 3 | //#include "mbed_debug.h" |
Geremia | 0:75ec1b3cde17 | 4 | //#define LCDPAGES (LCDSIZE_Y>>3) // 8raws per page |
Geremia | 0:75ec1b3cde17 | 5 | //#define IC_PAGES (IC_Y_COMS>>3) // max pages in IC ddram, 8raws per page |
Geremia | 0:75ec1b3cde17 | 6 | #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } |
Geremia | 0:75ec1b3cde17 | 7 | #define USEFRAMEBUFFER |
Geremia | 0:75ec1b3cde17 | 8 | //#define FRAMEBUFSIZE (LCDSIZE_X*LCDPAGES) |
Geremia | 0:75ec1b3cde17 | 9 | Protocols* proto; |
Geremia | 0:75ec1b3cde17 | 10 | |
Geremia | 0:75ec1b3cde17 | 11 | 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 | 0:75ec1b3cde17 | 12 | : /*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) |
Geremia | 0:75ec1b3cde17 | 13 | { |
Geremia | 0:75ec1b3cde17 | 14 | // LCDPAGES = LCDSIZE_Y>>3; |
Geremia | 0:75ec1b3cde17 | 15 | // IC_PAGES = IC_Y_COMS>>3; |
Geremia | 0:75ec1b3cde17 | 16 | // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; |
Geremia | 0:75ec1b3cde17 | 17 | // PAR8 par8proto(port, CS, reset, DC, WR, RD); |
Geremia | 0:75ec1b3cde17 | 18 | if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); |
Geremia | 0:75ec1b3cde17 | 19 | buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); |
Geremia | 0:75ec1b3cde17 | 20 | draw_mode = NORMAL; |
Geremia | 0:75ec1b3cde17 | 21 | set_orientation(1); |
Geremia | 0:75ec1b3cde17 | 22 | // cls(); |
Geremia | 0:75ec1b3cde17 | 23 | // locate(0,0); |
Geremia | 0:75ec1b3cde17 | 24 | } |
Geremia | 0:75ec1b3cde17 | 25 | 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) |
Geremia | 0:75ec1b3cde17 | 26 | : 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) |
Geremia | 0:75ec1b3cde17 | 27 | { |
Geremia | 0:75ec1b3cde17 | 28 | // LCDPAGES = LCDSIZE_Y>>3; |
Geremia | 0:75ec1b3cde17 | 29 | // IC_PAGES = IC_Y_COMS>>3; |
Geremia | 0:75ec1b3cde17 | 30 | // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; |
Geremia | 0:75ec1b3cde17 | 31 | // PAR8 par8proto(port, CS, reset, DC, WR, RD); |
Geremia | 0:75ec1b3cde17 | 32 | if(displayproto==SPI_8) proto = new SPI8(mosi, miso, sclk, CS, reset, DC); |
Geremia | 0:75ec1b3cde17 | 33 | buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); |
Geremia | 0:75ec1b3cde17 | 34 | draw_mode = NORMAL; |
Geremia | 0:75ec1b3cde17 | 35 | // cls(); |
Geremia | 0:75ec1b3cde17 | 36 | set_orientation(1); |
Geremia | 0:75ec1b3cde17 | 37 | // locate(0,0); |
Geremia | 0:75ec1b3cde17 | 38 | } |
Geremia | 0:75ec1b3cde17 | 39 | LCD::~LCD() |
Geremia | 0:75ec1b3cde17 | 40 | { |
Geremia | 0:75ec1b3cde17 | 41 | free(buffer); |
Geremia | 0:75ec1b3cde17 | 42 | } |
Geremia | 0:75ec1b3cde17 | 43 | |
Geremia | 0:75ec1b3cde17 | 44 | void LCD::wr_cmd(unsigned char cmd) |
Geremia | 0:75ec1b3cde17 | 45 | { |
Geremia | 0:75ec1b3cde17 | 46 | proto->wr_cmd(cmd); |
Geremia | 0:75ec1b3cde17 | 47 | } |
Geremia | 0:75ec1b3cde17 | 48 | void LCD::wr_data8(unsigned char data8) |
Geremia | 0:75ec1b3cde17 | 49 | { |
Geremia | 0:75ec1b3cde17 | 50 | proto->wr_data8(data8); |
Geremia | 0:75ec1b3cde17 | 51 | } |
Geremia | 0:75ec1b3cde17 | 52 | void LCD::wr_data8(unsigned char data8, unsigned int count) |
Geremia | 0:75ec1b3cde17 | 53 | { |
Geremia | 0:75ec1b3cde17 | 54 | proto->wr_data8(data8, count); |
Geremia | 0:75ec1b3cde17 | 55 | } |
Geremia | 0:75ec1b3cde17 | 56 | void LCD::wr_data8buf(unsigned char* data8, unsigned int lenght) |
Geremia | 0:75ec1b3cde17 | 57 | { |
Geremia | 0:75ec1b3cde17 | 58 | proto->wr_data8buf(data8, lenght); |
Geremia | 0:75ec1b3cde17 | 59 | } |
Geremia | 0:75ec1b3cde17 | 60 | void LCD::hw_reset() |
Geremia | 0:75ec1b3cde17 | 61 | { |
Geremia | 0:75ec1b3cde17 | 62 | proto->hw_reset(); |
Geremia | 0:75ec1b3cde17 | 63 | } |
Geremia | 0:75ec1b3cde17 | 64 | void LCD::BusEnable(bool enable) |
Geremia | 0:75ec1b3cde17 | 65 | { |
Geremia | 0:75ec1b3cde17 | 66 | proto->BusEnable(enable); |
Geremia | 0:75ec1b3cde17 | 67 | } |
Geremia | 0:75ec1b3cde17 | 68 | |
Geremia | 0:75ec1b3cde17 | 69 | |
Geremia | 0:75ec1b3cde17 | 70 | |
Geremia | 0:75ec1b3cde17 | 71 | // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays |
Geremia | 0:75ec1b3cde17 | 72 | // for portrait views, XY swap will be done in sw in pixel() function |
Geremia | 0:75ec1b3cde17 | 73 | void LCD::set_orientation(int o) |
Geremia | 0:75ec1b3cde17 | 74 | { |
Geremia | 0:75ec1b3cde17 | 75 | orientation = o; |
Geremia | 0:75ec1b3cde17 | 76 | switch (o) { |
Geremia | 0:75ec1b3cde17 | 77 | case (0):// portrait view -90° |
Geremia | 0:75ec1b3cde17 | 78 | mirrorXY(Y); |
Geremia | 0:75ec1b3cde17 | 79 | col_offset = 0; |
Geremia | 0:75ec1b3cde17 | 80 | page_offset = IC_PAGES-LCDPAGES; |
Geremia | 0:75ec1b3cde17 | 81 | set_width(LCDSIZE_Y); |
Geremia | 0:75ec1b3cde17 | 82 | set_height(LCDSIZE_X); |
Geremia | 0:75ec1b3cde17 | 83 | // portrait = true; |
Geremia | 0:75ec1b3cde17 | 84 | break; |
Geremia | 0:75ec1b3cde17 | 85 | case (1): // default, landscape view 0° |
Geremia | 0:75ec1b3cde17 | 86 | mirrorXY(NONE); |
Geremia | 0:75ec1b3cde17 | 87 | col_offset = 0; |
Geremia | 0:75ec1b3cde17 | 88 | page_offset = 0; |
Geremia | 0:75ec1b3cde17 | 89 | set_width(LCDSIZE_X); |
Geremia | 0:75ec1b3cde17 | 90 | set_height(LCDSIZE_Y); |
Geremia | 0:75ec1b3cde17 | 91 | // portrait = false; |
Geremia | 0:75ec1b3cde17 | 92 | break; |
Geremia | 0:75ec1b3cde17 | 93 | case (2):// portrait view +90° |
Geremia | 0:75ec1b3cde17 | 94 | mirrorXY(X); |
Geremia | 0:75ec1b3cde17 | 95 | col_offset = IC_X_SEGS-LCDSIZE_X; // some displays have less pixels than IC ram |
Geremia | 0:75ec1b3cde17 | 96 | page_offset = 0; |
Geremia | 0:75ec1b3cde17 | 97 | set_width(LCDSIZE_Y); |
Geremia | 0:75ec1b3cde17 | 98 | set_height(LCDSIZE_X); |
Geremia | 0:75ec1b3cde17 | 99 | // portrait = true; |
Geremia | 0:75ec1b3cde17 | 100 | break; |
Geremia | 0:75ec1b3cde17 | 101 | case (3):// landscape view +180° |
Geremia | 0:75ec1b3cde17 | 102 | mirrorXY(XY); |
Geremia | 0:75ec1b3cde17 | 103 | col_offset = IC_X_SEGS-LCDSIZE_X; |
Geremia | 0:75ec1b3cde17 | 104 | page_offset = IC_PAGES-LCDPAGES; |
Geremia | 0:75ec1b3cde17 | 105 | set_width(LCDSIZE_X); |
Geremia | 0:75ec1b3cde17 | 106 | set_height(LCDSIZE_Y); |
Geremia | 0:75ec1b3cde17 | 107 | // portrait = false; |
Geremia | 0:75ec1b3cde17 | 108 | break; |
Geremia | 0:75ec1b3cde17 | 109 | } |
Geremia | 0:75ec1b3cde17 | 110 | } |
Geremia | 0:75ec1b3cde17 | 111 | void LCD::mirrorXY(mirror_t mode) |
Geremia | 0:75ec1b3cde17 | 112 | { |
Geremia | 0:75ec1b3cde17 | 113 | switch (mode) |
Geremia | 0:75ec1b3cde17 | 114 | { |
Geremia | 0:75ec1b3cde17 | 115 | case(NONE): |
Geremia | 0:75ec1b3cde17 | 116 | wr_cmd(0xA0); |
Geremia | 0:75ec1b3cde17 | 117 | 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 |
Geremia | 0:75ec1b3cde17 | 118 | break; |
Geremia | 0:75ec1b3cde17 | 119 | case(X): |
Geremia | 0:75ec1b3cde17 | 120 | wr_cmd(0xA1); |
Geremia | 0:75ec1b3cde17 | 121 | wr_cmd(0xC8); |
Geremia | 0:75ec1b3cde17 | 122 | break; |
Geremia | 0:75ec1b3cde17 | 123 | case(Y): |
Geremia | 0:75ec1b3cde17 | 124 | wr_cmd(0xA0); |
Geremia | 0:75ec1b3cde17 | 125 | wr_cmd(0xC0); |
Geremia | 0:75ec1b3cde17 | 126 | break; |
Geremia | 0:75ec1b3cde17 | 127 | case(XY): |
Geremia | 0:75ec1b3cde17 | 128 | wr_cmd(0xA1); |
Geremia | 0:75ec1b3cde17 | 129 | wr_cmd(0xC0); |
Geremia | 0:75ec1b3cde17 | 130 | break; |
Geremia | 0:75ec1b3cde17 | 131 | } |
Geremia | 0:75ec1b3cde17 | 132 | } |
Geremia | 0:75ec1b3cde17 | 133 | void LCD::invert(unsigned char o) |
Geremia | 0:75ec1b3cde17 | 134 | { |
Geremia | 0:75ec1b3cde17 | 135 | if(o == 0) wr_cmd(0xA6); |
Geremia | 0:75ec1b3cde17 | 136 | else wr_cmd(0xA7); |
Geremia | 0:75ec1b3cde17 | 137 | } |
Geremia | 0:75ec1b3cde17 | 138 | |
Geremia | 0:75ec1b3cde17 | 139 | void LCD::set_contrast(int o) |
Geremia | 0:75ec1b3cde17 | 140 | { |
Geremia | 0:75ec1b3cde17 | 141 | contrast = o; |
Geremia | 0:75ec1b3cde17 | 142 | wr_cmd(0x81); // set volume |
Geremia | 0:75ec1b3cde17 | 143 | wr_cmd(o & 0x3F); |
Geremia | 0:75ec1b3cde17 | 144 | } |
Geremia | 0:75ec1b3cde17 | 145 | void LCD::set_auto_up(bool up) |
Geremia | 0:75ec1b3cde17 | 146 | { |
Geremia | 0:75ec1b3cde17 | 147 | if(up) auto_up = true; |
Geremia | 0:75ec1b3cde17 | 148 | else auto_up = false; |
Geremia | 0:75ec1b3cde17 | 149 | } |
Geremia | 0:75ec1b3cde17 | 150 | bool LCD::get_auto_up(void) |
Geremia | 0:75ec1b3cde17 | 151 | { |
Geremia | 0:75ec1b3cde17 | 152 | return (auto_up); |
Geremia | 0:75ec1b3cde17 | 153 | } |
Geremia | 0:75ec1b3cde17 | 154 | int LCD::get_contrast(void) |
Geremia | 0:75ec1b3cde17 | 155 | { |
Geremia | 0:75ec1b3cde17 | 156 | return(contrast); |
Geremia | 0:75ec1b3cde17 | 157 | } |
Geremia | 0:75ec1b3cde17 | 158 | void LCD::window(int x, int y, int w, int h) { |
Geremia | 0:75ec1b3cde17 | 159 | // current pixel location |
Geremia | 0:75ec1b3cde17 | 160 | cur_x = x; |
Geremia | 0:75ec1b3cde17 | 161 | cur_y = y; |
Geremia | 0:75ec1b3cde17 | 162 | // window settings |
Geremia | 0:75ec1b3cde17 | 163 | win_x1 = x; |
Geremia | 0:75ec1b3cde17 | 164 | win_x2 = x + w - 1; |
Geremia | 0:75ec1b3cde17 | 165 | win_y1 = y; |
Geremia | 0:75ec1b3cde17 | 166 | win_y2 = y + h - 1; |
Geremia | 0:75ec1b3cde17 | 167 | } |
Geremia | 0:75ec1b3cde17 | 168 | void LCD::window_pushpixel(unsigned short color) { |
Geremia | 0:75ec1b3cde17 | 169 | pixel(cur_x, cur_y, color); |
Geremia | 0:75ec1b3cde17 | 170 | cur_x++; |
Geremia | 0:75ec1b3cde17 | 171 | if(cur_x > win_x2) { |
Geremia | 0:75ec1b3cde17 | 172 | cur_x = win_x1; |
Geremia | 0:75ec1b3cde17 | 173 | cur_y++; |
Geremia | 0:75ec1b3cde17 | 174 | if(cur_y > win_y2) { |
Geremia | 0:75ec1b3cde17 | 175 | cur_y = win_y1; |
Geremia | 0:75ec1b3cde17 | 176 | } |
Geremia | 0:75ec1b3cde17 | 177 | } |
Geremia | 0:75ec1b3cde17 | 178 | } |
Geremia | 0:75ec1b3cde17 | 179 | void LCD::pixel(int x, int y, unsigned short color) |
Geremia | 0:75ec1b3cde17 | 180 | { |
Geremia | 0:75ec1b3cde17 | 181 | if(!(orientation&1)) SWAP(x,y); |
Geremia | 0:75ec1b3cde17 | 182 | // first check parameter |
Geremia | 0:75ec1b3cde17 | 183 | if((x >= LCDSIZE_X) || (y >= LCDSIZE_Y)) return; |
Geremia | 0:75ec1b3cde17 | 184 | |
Geremia | 0:75ec1b3cde17 | 185 | // if(draw_mode == NORMAL) |
Geremia | 0:75ec1b3cde17 | 186 | // { |
Geremia | 0:75ec1b3cde17 | 187 | if(color == 0) buffer[x + ((y>>3) * LCDSIZE_X)] &= ~(1 << (y&7)); // erase pixel |
Geremia | 0:75ec1b3cde17 | 188 | else buffer[x + ((y>>3) * LCDSIZE_X)] |= (1 << (y&7)); // set pixel |
Geremia | 0:75ec1b3cde17 | 189 | // } |
Geremia | 0:75ec1b3cde17 | 190 | // else |
Geremia | 0:75ec1b3cde17 | 191 | // { // XOR mode |
Geremia | 0:75ec1b3cde17 | 192 | // if(color == 1) buffer[x + ((y>>3) * LCDSIZE_X)] ^= (1 << (y&7)); // xor pixel |
Geremia | 0:75ec1b3cde17 | 193 | // } |
Geremia | 0:75ec1b3cde17 | 194 | } |
Geremia | 0:75ec1b3cde17 | 195 | void LCD::copy_to_lcd(void) |
Geremia | 0:75ec1b3cde17 | 196 | { |
Geremia | 0:75ec1b3cde17 | 197 | unsigned short i=0; |
Geremia | 0:75ec1b3cde17 | 198 | for(int page=0; page<LCDPAGES; page++) |
Geremia | 0:75ec1b3cde17 | 199 | { |
Geremia | 0:75ec1b3cde17 | 200 | wr_cmd((unsigned char)col_offset&0xF); // set column low nibble |
Geremia | 0:75ec1b3cde17 | 201 | wr_cmd(0x10|(col_offset>>4)); // set column hi nibble |
Geremia | 0:75ec1b3cde17 | 202 | wr_cmd(0xB0|(page+page_offset)); // set page |
Geremia | 0:75ec1b3cde17 | 203 | wr_data8buf(buffer+i, LCDSIZE_X); // send whole page pixels |
Geremia | 0:75ec1b3cde17 | 204 | i+=LCDSIZE_X; |
Geremia | 0:75ec1b3cde17 | 205 | } |
Geremia | 0:75ec1b3cde17 | 206 | } |
Geremia | 0:75ec1b3cde17 | 207 | void LCD::cls(void) |
Geremia | 0:75ec1b3cde17 | 208 | { |
Geremia | 0:75ec1b3cde17 | 209 | memset(buffer,0x00,LCDSIZE_X*LCDPAGES); // clear display buffer |
Geremia | 0:75ec1b3cde17 | 210 | for(int page=0; page<LCDPAGES; page++) |
Geremia | 0:75ec1b3cde17 | 211 | { |
Geremia | 0:75ec1b3cde17 | 212 | wr_cmd((unsigned char)col_offset&0xF); // set column low nibble |
Geremia | 0:75ec1b3cde17 | 213 | wr_cmd(0x10|(col_offset>>4)); // set column hi nibble |
Geremia | 0:75ec1b3cde17 | 214 | wr_cmd(0xB0|(page+page_offset)); // set page |
Geremia | 0:75ec1b3cde17 | 215 | wr_data8(0, LCDSIZE_X); // send whole page pixels =0 |
Geremia | 0:75ec1b3cde17 | 216 | } |
Geremia | 0:75ec1b3cde17 | 217 | } |