library for Sharp memory LCD (LS027B4DH01)

Dependents:   Sharp_Memory_LCD_Test Sharp_Memory_LCD_Test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sharp_mlcd.cpp Source File

sharp_mlcd.cpp

00001 /*
00002  * mbed library for the Sharp memory LCD LS027BDH01 / LS013B4DN04
00003  * derived from C12832_lcd
00004  * Copyright (c) 2014 Masato YAMANISHI
00005  * Released under the MIT License: http://mbed.org/license/mit
00006  */
00007 
00008 /* mbed library for the mbed Lab Board  128*32 pixel LCD
00009  * use C12832 controller
00010  * Copyright (c) 2012 Peter Drescher - DC2PD
00011  * Released under the MIT License: http://mbed.org/license/mit
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00016  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00019  * THE SOFTWARE.
00020  */
00021 
00022 // 13.10.12    initial design
00023 // 25.10.12    add autorefresh of screen
00024 // 25.10.12    add standart font
00025 // 20.12.12    add bitmap graphics
00026 
00027 // optional defines :
00028 // #define debug_lcd  1
00029 
00030 // #include "mbed.h"
00031 #include "sharp_mlcd.h"
00032 #include "stdio.h"
00033 #include "Small_7.h"
00034 
00035 sharp_mlcd::sharp_mlcd(const char* name)
00036   : _spi(D11,NC,D13),_EXTCOM(D9),_DISP(D8),_CS(D10), GraphicsDisplay(name) // for nucleo L152RE or other
00037 {
00038   draw_mode = NORMAL;
00039   char_x = 0;
00040   lcd_reset();
00041 }
00042 
00043 int sharp_mlcd::width()
00044 {
00045   return WIDTH;
00046 }
00047 
00048 int sharp_mlcd::height()
00049 {
00050   return HEIGHT; // 32;
00051 }
00052 
00053 // write command to lcd controller
00054 
00055 
00056 // reset and init the lcd controller
00057 
00058 void sharp_mlcd::lcd_reset()
00059 {
00060   _CS = 0;
00061   _spi.format(8, 0);                // 8 bit spi mode 0
00062   _spi.frequency(2000000);          // 2 Mhz SPI clock
00063   _DISP = 1;
00064   flip = 0;
00065   set_reverse_mode(0);
00066   // timer.attach(attime, 0.5); // 1KHz
00067 
00068   _CS = 1;
00069   wait_us(4);
00070   _spi.write(0x20); // 0x20:clear 0x00:run
00071   _spi.write(0); // dummy
00072   wait_us(2);
00073   _CS = 0;
00074 
00075   // clear and update LCD
00076   cls();
00077   // memset(buffer,0xff,BUFFER_SIZE);  // clear display buffer
00078   // copy_to_lcd();
00079   auto_up = 1;              // switch on auto update
00080   // dont do this by default. Make the user call
00081   //claim(stdout);           // redirekt printf to lcd
00082   locate(0,0);
00083   set_font((unsigned char*)Small_7);  // standart font
00084 }
00085 
00086 void sharp_mlcd::set_reverse_mode(unsigned int r = 0)
00087 {
00088   reverse = r;
00089 }
00090 
00091 // set one pixel in buffer
00092 
00093 void sharp_mlcd::pixel(int x, int y, int color)
00094 {
00095   // first check parameter
00096   if(x > WIDTH || y > HEIGHT || x < 0 || y < 0) return;
00097 
00098   if(draw_mode == NORMAL) {
00099     if(color != reverse)
00100       buffer[x/8 + (y*WIDTH/8)] &= ~(1 << (7-(x%8)));  // set pixel
00101     else
00102       buffer[x/8 + (y*WIDTH/8)] |= (1 << (7-(x%8)));   // erase pixel
00103   } else { // XOR mode
00104     if(color != reverse)
00105       buffer[x/8 + (y*WIDTH/8)] ^= (1 << (7-(x%8)));   // xor pixel
00106   }
00107 }
00108 
00109 // update lcd
00110 
00111 void sharp_mlcd::attime() {
00112   flip = !flip;
00113   _EXTCOM = flip;
00114 }
00115 
00116 unsigned char sharp_mlcd::bit_reverse(unsigned char c) {
00117   unsigned char u=0; // c = TESTVALUE;
00118   int i;
00119 
00120   for (i=0 ; i<4 ; i++)
00121     u |= ((c & (1 << i)) << (7-2*i)) | ((c & (1 << 7-i)) >> (7-2*i));
00122   return u;
00123 }
00124 
00125 void sharp_mlcd::copy_to_lcd(void)
00126 {
00127   const int start = 0;
00128   int x, y;
00129   unsigned char *p = (unsigned char*)buffer; // image;
00130     
00131   _CS = 1;
00132   wait_us(4); // min 3us
00133   //
00134   for (y = 0; y < HEIGHT; y++) {
00135     _spi.write(0x80); // update mode (multi line)
00136     _spi.write(bit_reverse((y + 1 + start) % HEIGHT)); // set gate line address
00137     for (x = 0; x < (WIDTH / 8); x++) {
00138       _spi.write(*p++); // (((y / 8) + x + mode) % 2)? 0xff: 0);
00139     }
00140   }
00141   //
00142   wait_us(2); // min 1us
00143   _CS = 0;
00144 }
00145 
00146 void sharp_mlcd::cls(void)
00147 {
00148   memset(buffer, reverse? 0x00: 0xff, BUFFER_SIZE);  // clear display buffer
00149   copy_to_lcd();
00150 }
00151 
00152 
00153 void sharp_mlcd::line(int x0, int y0, int x1, int y1, int color)
00154 {
00155   int   dx = 0, dy = 0;
00156   int   dx_sym = 0, dy_sym = 0;
00157   int   dx_x2 = 0, dy_x2 = 0;
00158   int   di = 0;
00159 
00160   dx = x1-x0;
00161   dy = y1-y0;
00162 
00163   //  if (dx == 0) {        /* vertical line */
00164   //      if (y1 > y0) vline(x0,y0,y1,color);
00165   //      else vline(x0,y1,y0,color);
00166   //      return;
00167   //  }
00168 
00169   if (dx > 0) {
00170     dx_sym = 1;
00171   } else {
00172     dx_sym = -1;
00173   }
00174   //  if (dy == 0) {        /* horizontal line */
00175   //      if (x1 > x0) hline(x0,x1,y0,color);
00176   //      else  hline(x1,x0,y0,color);
00177   //      return;
00178   //  }
00179 
00180   if (dy > 0) {
00181     dy_sym = 1;
00182   } else {
00183     dy_sym = -1;
00184   }
00185 
00186   dx = dx_sym*dx;
00187   dy = dy_sym*dy;
00188 
00189   dx_x2 = dx*2;
00190   dy_x2 = dy*2;
00191 
00192   if (dx >= dy) {
00193     di = dy_x2 - dx;
00194     while (x0 != x1) {
00195 
00196       pixel(x0, y0, color);
00197       x0 += dx_sym;
00198       if (di<0) {
00199         di += dy_x2;
00200       } else {
00201         di += dy_x2 - dx_x2;
00202         y0 += dy_sym;
00203       }
00204     }
00205     pixel(x0, y0, color);
00206   } else {
00207     di = dx_x2 - dy;
00208     while (y0 != y1) {
00209       pixel(x0, y0, color);
00210       y0 += dy_sym;
00211       if (di < 0) {
00212         di += dx_x2;
00213       } else {
00214         di += dx_x2 - dy_x2;
00215         x0 += dx_sym;
00216       }
00217     }
00218     pixel(x0, y0, color);
00219   }
00220   if(auto_up) copy_to_lcd();
00221 }
00222 
00223 void sharp_mlcd::rect(int x0, int y0, int x1, int y1, int color)
00224 {
00225 
00226   if (x1 > x0) line(x0,y0,x1,y0,color);
00227   else  line(x1,y0,x0,y0,color);
00228 
00229   if (y1 > y0) line(x0,y0,x0,y1,color);
00230   else line(x0,y1,x0,y0,color);
00231 
00232   if (x1 > x0) line(x0,y1,x1,y1,color);
00233   else  line(x1,y1,x0,y1,color);
00234 
00235   if (y1 > y0) line(x1,y0,x1,y1,color);
00236   else line(x1,y1,x1,y0,color);
00237 
00238   if(auto_up) copy_to_lcd();
00239 }
00240 
00241 void sharp_mlcd::fillrect(int x0, int y0, int x1, int y1, int color)
00242 {
00243   int l,c,i;
00244   if(x0 > x1) {
00245     i = x0;
00246     x0 = x1;
00247     x1 = i;
00248   }
00249 
00250   if(y0 > y1) {
00251     i = y0;
00252     y0 = y1;
00253     y1 = i;
00254   }
00255 
00256   for(l = x0; l<= x1; l ++) {
00257     for(c = y0; c<= y1; c++) {
00258       pixel(l,c,color);
00259     }
00260   }
00261   if(auto_up) copy_to_lcd();
00262 }
00263 
00264 
00265 
00266 void sharp_mlcd::circle(int x0, int y0, int r, int color)
00267 {
00268 
00269   int draw_x0, draw_y0;
00270   int draw_x1, draw_y1;
00271   int draw_x2, draw_y2;
00272   int draw_x3, draw_y3;
00273   int draw_x4, draw_y4;
00274   int draw_x5, draw_y5;
00275   int draw_x6, draw_y6;
00276   int draw_x7, draw_y7;
00277   int xx, yy;
00278   int di;
00279   //WindowMax();
00280   if (r == 0) {       /* no radius */
00281     return;
00282   }
00283 
00284   draw_x0 = draw_x1 = x0;
00285   draw_y0 = draw_y1 = y0 + r;
00286   if (draw_y0 < height()) {
00287     pixel(draw_x0, draw_y0, color);     /* 90 degree */
00288   }
00289 
00290   draw_x2 = draw_x3 = x0;
00291   draw_y2 = draw_y3 = y0 - r;
00292   if (draw_y2 >= 0) {
00293     pixel(draw_x2, draw_y2, color);    /* 270 degree */
00294   }
00295 
00296   draw_x4 = draw_x6 = x0 + r;
00297   draw_y4 = draw_y6 = y0;
00298   if (draw_x4 < width()) {
00299     pixel(draw_x4, draw_y4, color);     /* 0 degree */
00300   }
00301 
00302   draw_x5 = draw_x7 = x0 - r;
00303   draw_y5 = draw_y7 = y0;
00304   if (draw_x5>=0) {
00305     pixel(draw_x5, draw_y5, color);     /* 180 degree */
00306   }
00307 
00308   if (r == 1) {
00309     return;
00310   }
00311 
00312   di = 3 - 2*r;
00313   xx = 0;
00314   yy = r;
00315   while (xx < yy) {
00316 
00317     if (di < 0) {
00318       di += 4*xx + 6;
00319     } else {
00320       di += 4*(xx - yy) + 10;
00321       yy--;
00322       draw_y0--;
00323       draw_y1--;
00324       draw_y2++;
00325       draw_y3++;
00326       draw_x4--;
00327       draw_x5++;
00328       draw_x6--;
00329       draw_x7++;
00330     }
00331     xx++;
00332     draw_x0++;
00333     draw_x1--;
00334     draw_x2++;
00335     draw_x3--;
00336     draw_y4++;
00337     draw_y5++;
00338     draw_y6--;
00339     draw_y7--;
00340 
00341     if ( (draw_x0 <= width()) && (draw_y0>=0) ) {
00342       pixel(draw_x0, draw_y0, color);
00343     }
00344 
00345     if ( (draw_x1 >= 0) && (draw_y1 >= 0) ) {
00346       pixel(draw_x1, draw_y1, color);
00347     }
00348 
00349     if ( (draw_x2 <= width()) && (draw_y2 <= height()) ) {
00350       pixel(draw_x2, draw_y2, color);
00351     }
00352 
00353     if ( (draw_x3 >=0 ) && (draw_y3 <= height()) ) {
00354       pixel(draw_x3, draw_y3, color);
00355     }
00356 
00357     if ( (draw_x4 <= width()) && (draw_y4 >= 0) ) {
00358       pixel(draw_x4, draw_y4, color);
00359     }
00360 
00361     if ( (draw_x5 >= 0) && (draw_y5 >= 0) ) {
00362       pixel(draw_x5, draw_y5, color);
00363     }
00364     if ( (draw_x6 <=width()) && (draw_y6 <= height()) ) {
00365       pixel(draw_x6, draw_y6, color);
00366     }
00367     if ( (draw_x7 >= 0) && (draw_y7 <= height()) ) {
00368       pixel(draw_x7, draw_y7, color);
00369     }
00370   }
00371   if(auto_up) copy_to_lcd();
00372 }
00373 
00374 void sharp_mlcd::fillcircle(int x, int y, int r, int color)
00375 {
00376   int i,up;
00377   up = auto_up;
00378   auto_up = 0;   // off
00379   for (i = 0; i <= r; i++)
00380     circle(x,y,i,color);
00381   auto_up = up;
00382   if(auto_up) copy_to_lcd();
00383 }
00384 
00385 void sharp_mlcd::setmode(int mode)
00386 {
00387   draw_mode = mode;
00388 }
00389 
00390 void sharp_mlcd::locate(int x, int y)
00391 {
00392   char_x = x;
00393   char_y = y;
00394 }
00395 
00396 
00397 
00398 int sharp_mlcd::columns()
00399 {
00400   return width() / font[1];
00401 }
00402 
00403 
00404 
00405 int sharp_mlcd::rows()
00406 {
00407   return height() / font[2];
00408 }
00409 
00410 
00411 
00412 int sharp_mlcd::_putc(int value)
00413 {
00414   if (value == '\n') {    // new line
00415     char_x = 0;
00416     char_y = char_y + font[2];
00417     if (char_y >= height() - font[2]) {
00418       char_y = 0;
00419     }
00420   } else {
00421     character(char_x, char_y, value);
00422     if(auto_up) copy_to_lcd();
00423   }
00424   return value;
00425 }
00426 
00427 void sharp_mlcd::character(int x, int y, int c)
00428 {
00429   unsigned int hor,vert,offset,bpl,j,i,b;
00430   unsigned char* zeichen;
00431   unsigned char z,w;
00432 
00433   if ((c < 31) || (c > 127)) return;   // test char range
00434 
00435   // read font parameter from start of array
00436   offset = font[0];                    // bytes / char
00437   hor = font[1];                       // get hor size of font
00438   vert = font[2];                      // get vert size of font
00439   bpl = font[3];                       // bytes per line
00440 
00441   if (char_x + hor > width()) {
00442     char_x = 0;
00443     char_y = char_y + vert;
00444     if (char_y >= height() - font[2]) {
00445       char_y = 0;
00446     }
00447   }
00448 
00449   zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00450   w = zeichen[0];                          // width of actual char
00451   // construct the char into the buffer
00452   for (j=0; j<vert; j++) {  //  vert line
00453     for (i=0; i<hor; i++) {   //  horz line
00454       z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00455       b = 1 << (j & 0x07);
00456       if (( z & b ) == 0x00) {
00457         pixel(x+i,y+j,0);
00458       } else {
00459         pixel(x+i,y+j,1);
00460       }
00461 
00462     }
00463   }
00464 
00465   char_x += w;
00466 }
00467 
00468 void sharp_mlcd::set_font(unsigned char* f)
00469 {
00470   font = f;
00471 }
00472 
00473 void sharp_mlcd::set_auto_up(unsigned int up)
00474 {
00475   if(up ) auto_up = 1;
00476   else auto_up = 0;
00477 }
00478 
00479 unsigned int sharp_mlcd::get_auto_up(void)
00480 {
00481   return (auto_up);
00482 }
00483 
00484 void sharp_mlcd::print_bm(Bitmap bm, int x, int y, int color = 1)
00485 {
00486   int h,v,b;
00487   char d;
00488 
00489   for(v=0; v < bm.ySize; v++) {   // lines
00490     for(h=0; h < bm.xSize; h++) { // pixel
00491       if(h + x > WIDTH-1) break;
00492       if(v + y > HEIGHT-1) break;
00493       d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
00494       b = 0x80 >> (h & 0x07);
00495       if((d & b) == 0) {
00496         pixel(x+h,y+v,!color);
00497       } else {
00498         pixel(x+h,y+v,color);
00499       }
00500     }
00501   }
00502 }
00503