Extended library from C12832 Lib. by Peter Drescher, Chris Styles & Mihail Stoyanov. LCD in the market such as AQM1248A (Akizuki), AD-12864-SPI (antendo), NHD-C12832 (Newhaven), ST7565 (adafruit) and so on
Dependents: CW_Decoder_using_FFT_on_F446 LPC1114_SPI_LCD_ST7565family_test
Fork of C12832 by
ST7565_SPI_LCD.cpp
00001 /* 00002 EXTEND for SPI interface LCD which is using ST7565 controller 00003 Modified by Kenji Arai / JH1PJL 00004 http://www7b.biglobe.ne.jp/~kenjia/ 00005 https://os.mbed.com/users/kenjiArai/ 00006 Started: September 20th, 2014 00007 Revised: December 13th, 2014 00008 Revised: August 5th, 2020 00009 00010 original file: C12832.cpp 00011 original Library name: C12832 00012 */ 00013 00014 //---------- ORIGINAL Header --------------------------------------------------- 00015 /* mbed library for the mbed Lab Board 128*32 pixel LCD 00016 * use C12832 controller 00017 * Copyright (c) 2012 Peter Drescher - DC2PD 00018 * Released under the MIT License: http://mbed.org/license/mit 00019 * 00020 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00021 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00023 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00024 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00025 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00026 * THE SOFTWARE. 00027 */ 00028 00029 // 13.10.12 initial design 00030 // 25.10.12 add autorefresh of screen 00031 // 25.10.12 add standart font 00032 // 20.12.12 add bitmap graphics 00033 00034 #include "ST7565_SPI_LCD.h" 00035 #include "mbed.h" 00036 #include "stdio.h" 00037 #include "Small_7.h" 00038 00039 #define BPP 1 // Bits per pixel 00040 00041 //#define DEBUG 00042 // Com 00043 #ifdef DEBUG 00044 #define PRINTF(...) printf(__VA_ARGS__) 00045 #else 00046 #define PRINTF(...) {;} 00047 #endif 00048 00049 ST7565::ST7565 00050 ( 00051 PinName mosi, PinName sck, 00052 PinName reset, 00053 PinName a0, 00054 PinName ncs, 00055 LCDType type, 00056 const char* name 00057 ): 00058 GraphicsDisplay(name), 00059 _spi_p(new SPI(mosi,NC,sck)), _spi(*_spi_p), 00060 _reset(reset), 00061 _A0(a0), 00062 _CS(ncs) 00063 { 00064 initialize(type); 00065 } 00066 00067 ST7565::ST7565 00068 ( 00069 SPI& p_spi, 00070 PinName reset, 00071 PinName a0, 00072 PinName ncs, 00073 LCDType type, 00074 const char* name 00075 ): 00076 GraphicsDisplay(name), 00077 _spi(p_spi), 00078 _reset(reset), 00079 _A0(a0), 00080 _CS(ncs) 00081 { 00082 initialize(type); 00083 } 00084 00085 void ST7565::initialize(LCDType type) 00086 { 00087 switch (type) { 00088 case LCD128x32: 00089 lcd_width = 128; 00090 lcd_height = 32; 00091 break; 00092 case LCD128x48: 00093 lcd_width = 128; 00094 lcd_height = 48; 00095 break; 00096 case LCD128x64: 00097 lcd_width = 128; 00098 lcd_height = 64; 00099 break; 00100 default: 00101 lcd_width = 128; 00102 lcd_height = 64; 00103 } 00104 draw_mode = NORMAL; 00105 char_x = 0; 00106 lcd_reset(); 00107 } 00108 00109 int ST7565::width() 00110 { 00111 // PRINTF("W:%d",lcd_width); 00112 return(lcd_width); 00113 } 00114 00115 int ST7565::height() 00116 { 00117 // PRINTF("H:%d",lcd_height); 00118 return(lcd_height); 00119 } 00120 00121 void ST7565::invert(unsigned int o) 00122 { 00123 if(o == 0) { 00124 wr_cmd(0xA6); 00125 } else { 00126 wr_cmd(0xA7); 00127 } 00128 } 00129 00130 void ST7565::set_contrast(unsigned int o) 00131 { 00132 contrast = o; 00133 wr_cmd(0x23); // Vo voltage reg. 00134 wr_cmd(0x81); // set volume 00135 wr_cmd(o & 0x3F); 00136 } 00137 00138 unsigned int ST7565::get_contrast(void) 00139 { 00140 return(contrast); 00141 } 00142 00143 // write command to lcd controller 00144 void ST7565::wr_cmd(unsigned char cmd) 00145 { 00146 _A0 = 0; 00147 _CS = 0; 00148 _spi.write(cmd); 00149 _CS = 1; 00150 } 00151 00152 // write data to lcd controller 00153 void ST7565::wr_dat(unsigned char dat) 00154 { 00155 _A0 = 1; 00156 _CS = 0; 00157 _spi.write(dat); 00158 _CS = 1; 00159 } 00160 00161 // reset and init the lcd controller 00162 void ST7565::lcd_reset() 00163 { 00164 _spi.format(8,0); 00165 _spi.frequency(10000000); // 10 MHz SPI clock 00166 _A0 = 0; 00167 _CS = 1; 00168 _reset = 0; // display reset 00169 wait_us(50); 00170 _reset = 1; // end reset 00171 ThisThread::sleep_for(5ms); 00172 // initialize sequence 00173 wr_cmd(0xaf); // display on 00174 wr_cmd(0x2f); // power control set 00175 wr_cmd(0x81); // set electronic volume mode 00176 wr_cmd(0x00); // electronic volume data 00-3f 00177 wr_cmd(0x27); // Volatge Regulator Internal Resister Ratio Set 00178 wr_cmd(0xa2); // LCD Bias Set ... 1/9 bias 00179 wr_cmd(0xc8); // Common Output Mode Select ... Reverse 00180 wr_cmd(0xa0); // ADC Select ... Norma 00181 wr_cmd(0xa4); // Display All Points ON/OFF ... normal 00182 wr_cmd(0xa6); // Display Normal/Reverse ... normal 00183 wr_cmd(0xac); // Static Indicator ... off 00184 wr_cmd(0x00); // off 00185 wr_cmd(0x40); // Display Strat Line Set ... 0 00186 wr_cmd(0xe0); // Write Mode Set 00187 // clear and update LCD 00188 memset(buffer,0x00,1024); // clear display buffer 00189 copy_to_lcd(); 00190 auto_up = 1; // switch on auto update 00191 // dont do this by default. Make the user call 00192 //claim(stdout); // redirect printf to lcd 00193 locate(0,0); 00194 set_font((unsigned char*)Small_7); // standart font 00195 } 00196 00197 // set one pixel in buffer 00198 void ST7565::pixel(int x, int y, int color) 00199 { 00200 // first check parameter 00201 if(x > lcd_width || y > lcd_height || x < 0 || y < 0) return; 00202 if(draw_mode == NORMAL) { 00203 if(color == 0) 00204 buffer[x + ((y/8) * 128)] &= ~(1 << (y%8)); // erase pixel 00205 else 00206 buffer[x + ((y/8) * 128)] |= (1 << (y%8)); // set pixel 00207 } else { // XOR mode 00208 if(color == 1) 00209 buffer[x + ((y/8) * 128)] ^= (1 << (y%8)); // xor pixel 00210 } 00211 } 00212 00213 // update lcd 00214 void ST7565::copy_to_lcd(void) 00215 { 00216 int i=0; 00217 00218 // page 0 00219 wr_cmd(0x00); // set column low nibble 0 00220 wr_cmd(0x10); // set column hi nibble 0 00221 wr_cmd(0xB0); // set page address 0 00222 _A0 = 1; 00223 for(i=0; i<128; i++) { 00224 wr_dat(buffer[i]); 00225 } 00226 // page 1 00227 wr_cmd(0x00); // set column low nibble 0 00228 wr_cmd(0x10); // set column hi nibble 0 00229 wr_cmd(0xB1); // set page address 1 00230 _A0 = 1; 00231 for(i=128; i<256; i++) { 00232 wr_dat(buffer[i]); 00233 } 00234 // page 2 00235 wr_cmd(0x00); // set column low nibble 0 00236 wr_cmd(0x10); // set column hi nibble 0 00237 wr_cmd(0xB2); // set page address 2 00238 _A0 = 1; 00239 for(i=256; i<384; i++) { 00240 wr_dat(buffer[i]); 00241 } 00242 // page 3 00243 wr_cmd(0x00); // set column low nibble 0 00244 wr_cmd(0x10); // set column hi nibble 0 00245 wr_cmd(0xB3); // set page address 3 00246 _A0 = 1; 00247 for(i=384; i<512; i++) { 00248 wr_dat(buffer[i]); 00249 } 00250 if ((lcd_height == 48) || (lcd_height == 64)) { 00251 // page 4 00252 wr_cmd(0x00); // set column low nibble 0 00253 wr_cmd(0x10); // set column hi nibble 0 00254 wr_cmd(0xB4); // set page address 4 00255 _A0 = 1; 00256 for(i=512; i<640; i++) { 00257 wr_dat(buffer[i]); 00258 } 00259 // page 5 00260 wr_cmd(0x00); // set column low nibble 0 00261 wr_cmd(0x10); // set column hi nibble 0 00262 wr_cmd(0xB5); // set page address 5 00263 _A0 = 1; 00264 for(i=640; i<768; i++) { 00265 wr_dat(buffer[i]); 00266 } 00267 } 00268 if (lcd_height == 64) { 00269 // page 6 00270 wr_cmd(0x00); // set column low nibble 0 00271 wr_cmd(0x10); // set column hi nibble 0 00272 wr_cmd(0xB6); // set page address 6 00273 _A0 = 1; 00274 for(i=768; i<896; i++) { 00275 wr_dat(buffer[i]); 00276 } 00277 // page 7 00278 wr_cmd(0x00); // set column low nibble 0 00279 wr_cmd(0x10); // set column hi nibble 0 00280 wr_cmd(0xB7); // set page address 7 00281 _A0 = 1; 00282 for(i=896; i<1024; i++) { 00283 wr_dat(buffer[i]); 00284 } 00285 } 00286 _CS = 0; 00287 } 00288 00289 void ST7565::cls(void) 00290 { 00291 memset(buffer,0x00,1024); // clear display buffer 00292 copy_to_lcd(); 00293 } 00294 00295 void ST7565::line(int x0, int y0, int x1, int y1, int color) 00296 { 00297 int dx = 0, dy = 0; 00298 int dx_sym = 0, dy_sym = 0; 00299 int dx_x2 = 0, dy_x2 = 0; 00300 int di = 0; 00301 00302 dx = x1-x0; 00303 dy = y1-y0; 00304 // if (dx == 0) { /* vertical line */ 00305 // if (y1 > y0) vline(x0,y0,y1,color); 00306 // else vline(x0,y1,y0,color); 00307 // return; 00308 // } 00309 if (dx > 0) { 00310 dx_sym = 1; 00311 } else { 00312 dx_sym = -1; 00313 } 00314 // if (dy == 0) { /* horizontal line */ 00315 // if (x1 > x0) hline(x0,x1,y0,color); 00316 // else hline(x1,x0,y0,color); 00317 // return; 00318 // } 00319 if (dy > 0) { 00320 dy_sym = 1; 00321 } else { 00322 dy_sym = -1; 00323 } 00324 dx = dx_sym*dx; 00325 dy = dy_sym*dy; 00326 dx_x2 = dx*2; 00327 dy_x2 = dy*2; 00328 if (dx >= dy) { 00329 di = dy_x2 - dx; 00330 while (x0 != x1) { 00331 pixel(x0, y0, color); 00332 x0 += dx_sym; 00333 if (di<0) { 00334 di += dy_x2; 00335 } else { 00336 di += dy_x2 - dx_x2; 00337 y0 += dy_sym; 00338 } 00339 } 00340 pixel(x0, y0, color); 00341 } else { 00342 di = dx_x2 - dy; 00343 while (y0 != y1) { 00344 pixel(x0, y0, color); 00345 y0 += dy_sym; 00346 if (di < 0) { 00347 di += dx_x2; 00348 } else { 00349 di += dx_x2 - dy_x2; 00350 x0 += dx_sym; 00351 } 00352 } 00353 pixel(x0, y0, color); 00354 } 00355 if(auto_up) { 00356 copy_to_lcd(); 00357 } 00358 } 00359 00360 void ST7565::rect(int x0, int y0, int x1, int y1, int color) 00361 { 00362 if (x1 > x0) { 00363 line(x0,y0,x1,y0,color); 00364 } else { 00365 line(x1,y0,x0,y0,color); 00366 } 00367 if (y1 > y0) { 00368 line(x0,y0,x0,y1,color); 00369 } else { 00370 line(x0,y1,x0,y0,color); 00371 } 00372 if (x1 > x0) { 00373 line(x0,y1,x1,y1,color); 00374 } else { 00375 line(x1,y1,x0,y1,color); 00376 } 00377 if (y1 > y0) { 00378 line(x1,y0,x1,y1,color); 00379 } else { 00380 line(x1,y1,x1,y0,color); 00381 } 00382 if(auto_up) { 00383 copy_to_lcd(); 00384 } 00385 } 00386 00387 void ST7565::fillrect(int x0, int y0, int x1, int y1, int color) 00388 { 00389 int l,c,i; 00390 00391 if(x0 > x1) { 00392 i = x0; 00393 x0 = x1; 00394 x1 = i; 00395 } 00396 if(y0 > y1) { 00397 i = y0; 00398 y0 = y1; 00399 y1 = i; 00400 } 00401 for(l = x0; l<= x1; l ++) { 00402 for(c = y0; c<= y1; c++) { 00403 pixel(l,c,color); 00404 } 00405 } 00406 if(auto_up) { 00407 copy_to_lcd(); 00408 } 00409 } 00410 00411 void ST7565::circle(int x0, int y0, int r, int color) 00412 { 00413 int draw_x0, draw_y0; 00414 int draw_x1, draw_y1; 00415 int draw_x2, draw_y2; 00416 int draw_x3, draw_y3; 00417 int draw_x4, draw_y4; 00418 int draw_x5, draw_y5; 00419 int draw_x6, draw_y6; 00420 int draw_x7, draw_y7; 00421 int xx, yy; 00422 int di; 00423 00424 //WindowMax(); 00425 if (r == 0) { /* no radius */ 00426 return; 00427 } 00428 draw_x0 = draw_x1 = x0; 00429 draw_y0 = draw_y1 = y0 + r; 00430 if (draw_y0 < height()) { 00431 pixel(draw_x0, draw_y0, color); /* 90 degree */ 00432 } 00433 draw_x2 = draw_x3 = x0; 00434 draw_y2 = draw_y3 = y0 - r; 00435 if (draw_y2 >= 0) { 00436 pixel(draw_x2, draw_y2, color); /* 270 degree */ 00437 } 00438 draw_x4 = draw_x6 = x0 + r; 00439 draw_y4 = draw_y6 = y0; 00440 if (draw_x4 < width()) { 00441 pixel(draw_x4, draw_y4, color); /* 0 degree */ 00442 } 00443 draw_x5 = draw_x7 = x0 - r; 00444 draw_y5 = draw_y7 = y0; 00445 if (draw_x5>=0) { 00446 pixel(draw_x5, draw_y5, color); /* 180 degree */ 00447 } 00448 if (r == 1) { 00449 return; 00450 } 00451 di = 3 - 2*r; 00452 xx = 0; 00453 yy = r; 00454 while (xx < yy) { 00455 if (di < 0) { 00456 di += 4*xx + 6; 00457 } else { 00458 di += 4*(xx - yy) + 10; 00459 yy--; 00460 draw_y0--; 00461 draw_y1--; 00462 draw_y2++; 00463 draw_y3++; 00464 draw_x4--; 00465 draw_x5++; 00466 draw_x6--; 00467 draw_x7++; 00468 } 00469 xx++; 00470 draw_x0++; 00471 draw_x1--; 00472 draw_x2++; 00473 draw_x3--; 00474 draw_y4++; 00475 draw_y5++; 00476 draw_y6--; 00477 draw_y7--; 00478 if ((draw_x0 <= width()) && (draw_y0>=0)) { 00479 pixel(draw_x0, draw_y0, color); 00480 } 00481 if ((draw_x1 >= 0) && (draw_y1 >= 0)) { 00482 pixel(draw_x1, draw_y1, color); 00483 } 00484 if ((draw_x2 <= width()) && (draw_y2 <= height())) { 00485 pixel(draw_x2, draw_y2, color); 00486 } 00487 if ((draw_x3 >=0 ) && (draw_y3 <= height())) { 00488 pixel(draw_x3, draw_y3, color); 00489 } 00490 if ((draw_x4 <= width()) && (draw_y4 >= 0)) { 00491 pixel(draw_x4, draw_y4, color); 00492 } 00493 if ((draw_x5 >= 0) && (draw_y5 >= 0)) { 00494 pixel(draw_x5, draw_y5, color); 00495 } 00496 if ((draw_x6 <=width()) && (draw_y6 <= height())) { 00497 pixel(draw_x6, draw_y6, color); 00498 } 00499 if ((draw_x7 >= 0) && (draw_y7 <= height())) { 00500 pixel(draw_x7, draw_y7, color); 00501 } 00502 } 00503 if(auto_up) { 00504 copy_to_lcd(); 00505 } 00506 } 00507 00508 void ST7565::fillcircle(int x, int y, int r, int color) 00509 { 00510 int i,up; 00511 00512 up = auto_up; 00513 auto_up = 0; // off 00514 for (i = 0; i <= r; i++) { 00515 circle(x,y,i,color); 00516 } 00517 auto_up = up; 00518 if(auto_up) { 00519 copy_to_lcd(); 00520 } 00521 } 00522 00523 void ST7565::setmode(int mode) 00524 { 00525 draw_mode = mode; 00526 } 00527 00528 void ST7565::locate(int x, int y) 00529 { 00530 char_x = x; 00531 char_y = y; 00532 } 00533 00534 int ST7565::columns() 00535 { 00536 return width() / font[1]; 00537 } 00538 00539 int ST7565::rows() 00540 { 00541 return height() / font[2]; 00542 } 00543 00544 void ST7565::line_clear(int y) 00545 { 00546 unsigned int vert,j,i,x; 00547 00548 // read font parameter from start of array 00549 vert = font[2]; // get vert size of font 00550 x = 0; 00551 for (j=0; j<vert; j++) { // vert line 00552 for (i=0; i<width(); i++) { // horz line 00553 pixel(x+i,y+j,0); 00554 } 00555 } 00556 } 00557 00558 int ST7565::_putc(int value) 00559 { 00560 if (value == 0x0d) { // new line 00561 char_x = 0; 00562 char_y = char_y + font[2]; 00563 if (char_y >= height() - font[2]) { 00564 char_y = 0; 00565 } 00566 line_clear(char_y); 00567 } else { 00568 character(char_x, char_y, value); 00569 if(auto_up) { 00570 copy_to_lcd(); 00571 } 00572 } 00573 return value; 00574 } 00575 00576 void ST7565::character(int x, int y, int c) 00577 { 00578 unsigned int hor,vert,offset,bpl,j,i,b; 00579 unsigned char* zeichen; 00580 unsigned char z,w; 00581 00582 if ((c < 31) || (c > 127)) { 00583 return; // test char range 00584 } 00585 // read font parameter from start of array 00586 offset = font[0]; // bytes / char 00587 hor = font[1]; // get hor size of font 00588 vert = font[2]; // get vert size of font 00589 bpl = font[3]; // bytes per line 00590 if (char_x + hor > width()) { 00591 char_x = 0; 00592 char_y = char_y + vert; 00593 if (char_y >= height() - font[2]) { 00594 char_y = 0; 00595 } 00596 } 00597 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00598 w = zeichen[0]; // width of actual char 00599 // construct the char into the buffer 00600 for (j=0; j<vert; j++) { // vert line 00601 for (i=0; i<hor; i++) { // horz line 00602 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00603 b = 1 << (j & 0x07); 00604 if (( z & b ) == 0x00) { 00605 pixel(x+i,y+j,0); 00606 } else { 00607 pixel(x+i,y+j,1); 00608 } 00609 } 00610 } 00611 char_x += w; 00612 if(char_x >= (width() - hor)) { 00613 char_x = 0; 00614 char_y = char_y + vert; 00615 if (char_y >= height() - font[2]) { 00616 char_y = 0; 00617 } 00618 line_clear(char_y); 00619 } 00620 //PRINTF("C:%d %d %d %d %d %d\r\n",offset,hor,vert,bpl,char_x,char_y); 00621 } 00622 00623 void ST7565::set_font(unsigned char* f) 00624 { 00625 font = f; 00626 } 00627 00628 void ST7565::set_auto_up(unsigned int up) 00629 { 00630 if(up) { 00631 auto_up = 1; 00632 } else { 00633 auto_up = 0; 00634 } 00635 } 00636 00637 unsigned int ST7565::get_auto_up(void) 00638 { 00639 return (auto_up); 00640 } 00641 00642 void ST7565::print_bm(Bitmap bm, int x, int y) 00643 { 00644 int h,v,b; 00645 char d; 00646 00647 for(v=0; v < bm.ySize; v++) { // lines 00648 for(h=0; h < bm.xSize; h++) { // pixel 00649 if(h + x > 127) { 00650 break; 00651 } 00652 if(v + y > 31) { 00653 break; 00654 } 00655 d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)]; 00656 b = 0x80 >> (h & 0x07); 00657 if((d & b) == 0) { 00658 pixel(x+h,y+v,0); 00659 } else { 00660 pixel(x+h,y+v,1); 00661 } 00662 } 00663 } 00664 }
Generated on Tue Jul 12 2022 20:40:34 by 1.7.2