fixed library.

Dependents:   Sharp_Memory_LCD_Test hello_GT20L16J1Y_FONT_mlcd

Fork of sharp_mlcd by Masato YAMANISHI

sharp_mlcd.cpp

Committer:
ban4jp
Date:
2014-09-21
Revision:
3:d2aed1df064c
Parent:
2:c36cdd3ad7ba

File content as of revision 3:d2aed1df064c:

/*
 * mbed library for the Sharp memory LCD LS027BDH01 / LS013B4DN04
 * derived from C12832_lcd
 * Copyright (c) 2014 Masato YAMANISHI
 * Released under the MIT License: http://mbed.org/license/mit
 */

/* mbed library for the mbed Lab Board  128*32 pixel LCD
 * use C12832 controller
 * Copyright (c) 2012 Peter Drescher - DC2PD
 * Released under the MIT License: http://mbed.org/license/mit
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

// 13.10.12    initial design
// 25.10.12    add autorefresh of screen
// 25.10.12    add standart font
// 20.12.12    add bitmap graphics

// optional defines :
// #define debug_lcd  1

// #include "mbed.h"
#include "sharp_mlcd.h"
#include "stdio.h"
#include "Small_7.h"

sharp_mlcd::sharp_mlcd(const char* name)
  : GraphicsDisplay(name), _spi(D11, NC, D13), _EXTCOM(D9), _DISP(D8), _CS(D10)  // for nucleo L152RE or other
{
  lcd_reset();
}

sharp_mlcd::sharp_mlcd(PinName mosi, PinName sclk, PinName scs, PinName extcomin, PinName disp, const char* name)
  : GraphicsDisplay(name), _spi(mosi, NC, sclk), _EXTCOM(extcomin), _DISP(disp), _CS(scs)
{
  lcd_reset();
}

int sharp_mlcd::width()
{
  return WIDTH;
}

int sharp_mlcd::height()
{
  return HEIGHT; // 32;
}

// write command to lcd controller


// reset and init the lcd controller

void sharp_mlcd::lcd_reset()
{
  _CS = 0;
  _spi.format(8, 0);                // 8 bit spi mode 0
  _spi.frequency(2000000);          // 2 Mhz SPI clock
  _DISP = 1;
  flip = 0;
  set_reverse_mode(0);
  // timer.attach(attime, 0.5); // 1KHz

  _CS = 1;
  wait_us(4);
  _spi.write(0x20); // 0x20:clear 0x00:run
  _spi.write(0); // dummy
  wait_us(2);
  _CS = 0;

  setmode(NORMAL);

  // clear and update LCD
  cls();
  // memset(buffer,0xff,BUFFER_SIZE);  // clear display buffer
  // copy_to_lcd();
  auto_up = 1;              // switch on auto update
  // dont do this by default. Make the user call
  //claim(stdout);           // redirekt printf to lcd
  locate(0,0);
  set_font((unsigned char*)Small_7);  // standart font
}

void sharp_mlcd::set_reverse_mode(unsigned int r = 0)
{
  reverse = r;
}

// set one pixel in buffer

void sharp_mlcd::pixel(int x, int y, int color)
{
  // first check parameter
  if(x >= width() || y >= height() || x < 0 || y < 0) return;

  if(draw_mode == NORMAL) {
    if(color != reverse)
      buffer[x/8 + (y*width()/8)] &= ~(1 << (7-(x%8)));  // set pixel
    else
      buffer[x/8 + (y*width()/8)] |= (1 << (7-(x%8)));   // erase pixel
  } else { // XOR mode
    if(color != reverse)
      buffer[x/8 + (y*width()/8)] ^= (1 << (7-(x%8)));   // xor pixel
  }
}

// update lcd

void sharp_mlcd::attime() {
  flip = !flip;
  _EXTCOM = flip;
}

unsigned char sharp_mlcd::bit_reverse(unsigned char c) {
  unsigned char u=0; // c = TESTVALUE;
  int i;

  for (i=0 ; i<4 ; i++)
    u |= ((c & (1 << i)) << (7-2*i)) | ((c & (1 << 7-i)) >> (7-2*i));
  return u;
}

void sharp_mlcd::copy_to_lcd(int start)
{
  int x, y;
  unsigned char *p = (unsigned char*)buffer; // image;
    
  //_spi.begin();
  _spi.write(0);  // Dummy (mbed: change SPI owner and SPI format.)
  
  _CS = 1;
  wait_us(4); // min 3us
  //
  for (y = 0; y < height(); y++) {
    _spi.write(0x80); // update mode (multi line)
    _spi.write(bit_reverse((y + start) % height() + 1)); // set gate line address
    for (x = 0; x < (width() / 8); x++) {
      _spi.write(*p++); // (((y / 8) + x + mode) % 2)? 0xff: 0);
    }
  }
  _spi.write(0x00); // dummy (16ck)
  _spi.write(0x00);
  //
  wait_us(2); // min 1us
  _CS = 0;
}

void sharp_mlcd::cls(void)
{
  memset(buffer, reverse ? 0x00 : 0xff, BUFFER_SIZE);  // clear display buffer
  copy_to_lcd();
}


void sharp_mlcd::line(int x0, int y0, int x1, int y1, int color)
{
  int   dx = 0, dy = 0;
  int   dx_sym = 0, dy_sym = 0;
  int   dx_x2 = 0, dy_x2 = 0;
  int   di = 0;

  dx = x1-x0;
  dy = y1-y0;

  //  if (dx == 0) {        /* vertical line */
  //      if (y1 > y0) vline(x0,y0,y1,color);
  //      else vline(x0,y1,y0,color);
  //      return;
  //  }

  if (dx > 0) {
    dx_sym = 1;
  } else {
    dx_sym = -1;
  }
  //  if (dy == 0) {        /* horizontal line */
  //      if (x1 > x0) hline(x0,x1,y0,color);
  //      else  hline(x1,x0,y0,color);
  //      return;
  //  }

  if (dy > 0) {
    dy_sym = 1;
  } else {
    dy_sym = -1;
  }

  dx = dx_sym*dx;
  dy = dy_sym*dy;

  dx_x2 = dx*2;
  dy_x2 = dy*2;

  if (dx >= dy) {
    di = dy_x2 - dx;
    while (x0 != x1) {

      pixel(x0, y0, color);
      x0 += dx_sym;
      if (di<0) {
        di += dy_x2;
      } else {
        di += dy_x2 - dx_x2;
        y0 += dy_sym;
      }
    }
    pixel(x0, y0, color);
  } else {
    di = dx_x2 - dy;
    while (y0 != y1) {
      pixel(x0, y0, color);
      y0 += dy_sym;
      if (di < 0) {
        di += dx_x2;
      } else {
        di += dx_x2 - dy_x2;
        x0 += dx_sym;
      }
    }
    pixel(x0, y0, color);
  }
  if(auto_up) copy_to_lcd();
}

void sharp_mlcd::rect(int x0, int y0, int x1, int y1, int color)
{

  if (x1 > x0) line(x0,y0,x1,y0,color);
  else  line(x1,y0,x0,y0,color);

  if (y1 > y0) line(x0,y0,x0,y1,color);
  else line(x0,y1,x0,y0,color);

  if (x1 > x0) line(x0,y1,x1,y1,color);
  else  line(x1,y1,x0,y1,color);

  if (y1 > y0) line(x1,y0,x1,y1,color);
  else line(x1,y1,x1,y0,color);

  if(auto_up) copy_to_lcd();
}

void sharp_mlcd::fillrect(int x0, int y0, int x1, int y1, int color)
{
  int l,c,i;
  if(x0 > x1) {
    i = x0;
    x0 = x1;
    x1 = i;
  }

  if(y0 > y1) {
    i = y0;
    y0 = y1;
    y1 = i;
  }

  for(l = x0; l<= x1; l ++) {
    for(c = y0; c<= y1; c++) {
      pixel(l,c,color);
    }
  }
  if(auto_up) copy_to_lcd();
}



void sharp_mlcd::circle(int x0, int y0, int r, int color)
{

  int draw_x0, draw_y0;
  int draw_x1, draw_y1;
  int draw_x2, draw_y2;
  int draw_x3, draw_y3;
  int draw_x4, draw_y4;
  int draw_x5, draw_y5;
  int draw_x6, draw_y6;
  int draw_x7, draw_y7;
  int xx, yy;
  int di;
  //WindowMax();
  if (r == 0) {       /* no radius */
    return;
  }

  draw_x0 = draw_x1 = x0;
  draw_y0 = draw_y1 = y0 + r;
  if (draw_y0 < height()) {
    pixel(draw_x0, draw_y0, color);     /* 90 degree */
  }

  draw_x2 = draw_x3 = x0;
  draw_y2 = draw_y3 = y0 - r;
  if (draw_y2 >= 0) {
    pixel(draw_x2, draw_y2, color);    /* 270 degree */
  }

  draw_x4 = draw_x6 = x0 + r;
  draw_y4 = draw_y6 = y0;
  if (draw_x4 < width()) {
    pixel(draw_x4, draw_y4, color);     /* 0 degree */
  }

  draw_x5 = draw_x7 = x0 - r;
  draw_y5 = draw_y7 = y0;
  if (draw_x5 >= 0) {
    pixel(draw_x5, draw_y5, color);     /* 180 degree */
  }

  if (r == 1) {
    return;
  }

  di = 3 - 2*r;
  xx = 0;
  yy = r;
  while (xx < yy) {

    if (di < 0) {
      di += 4*xx + 6;
    } else {
      di += 4*(xx - yy) + 10;
      yy--;
      draw_y0--;
      draw_y1--;
      draw_y2++;
      draw_y3++;
      draw_x4--;
      draw_x5++;
      draw_x6--;
      draw_x7++;
    }
    xx++;
    draw_x0++;
    draw_x1--;
    draw_x2++;
    draw_x3--;
    draw_y4++;
    draw_y5++;
    draw_y6--;
    draw_y7--;

    if ( (draw_x0 <= width()) && (draw_y0 >= 0) ) {
      pixel(draw_x0, draw_y0, color);
    }

    if ( (draw_x1 >= 0) && (draw_y1 >= 0) ) {
      pixel(draw_x1, draw_y1, color);
    }

    if ( (draw_x2 <= width()) && (draw_y2 <= height()) ) {
      pixel(draw_x2, draw_y2, color);
    }

    if ( (draw_x3 >= 0 ) && (draw_y3 <= height()) ) {
      pixel(draw_x3, draw_y3, color);
    }

    if ( (draw_x4 <= width()) && (draw_y4 >= 0) ) {
      pixel(draw_x4, draw_y4, color);
    }

    if ( (draw_x5 >= 0) && (draw_y5 >= 0) ) {
      pixel(draw_x5, draw_y5, color);
    }
    if ( (draw_x6 <= width()) && (draw_y6 <= height()) ) {
      pixel(draw_x6, draw_y6, color);
    }
    if ( (draw_x7 >= 0) && (draw_y7 <= height()) ) {
      pixel(draw_x7, draw_y7, color);
    }
  }
  if(auto_up) copy_to_lcd();
}

void sharp_mlcd::fillcircle(int x, int y, int r, int color)
{
  int i,up;
  up = auto_up;
  auto_up = 0;   // off
  for (i = 0; i <= r; i++)
    circle(x,y,i,color);
  auto_up = up;
  if(auto_up) copy_to_lcd();
}

void sharp_mlcd::setmode(int mode)
{
  draw_mode = mode;
}

void sharp_mlcd::locate(int x, int y)
{
  char_x = x;
  char_y = y;
}



int sharp_mlcd::columns()
{
  return width() / font[1];
}



int sharp_mlcd::rows()
{
  return height() / font[2];
}



int sharp_mlcd::_putc(int value)
{
  if (value == '\n') {    // new line
    char_x = 0;
    char_y = char_y + font[2];
    if (char_y > height() - font[2]) {
      char_y = 0;
    }
  } else {
    character(char_x, char_y, value);
    if(auto_up) copy_to_lcd();
  }
  return value;
}

void sharp_mlcd::character(int x, int y, int c)
{
  unsigned int hor,vert,offset,bpl,j,i,b;
  unsigned char* zeichen;
  unsigned char z,w;

  if ((c < 31) || (c > 127)) return;   // test char range

  // read font parameter from start of array
  offset = font[0];                    // bytes / char
  hor = font[1];                       // get hor size of font
  vert = font[2];                      // get vert size of font
  bpl = font[3];                       // bytes per line

  zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
  w = zeichen[0];                          // width of actual char

  if (char_x > width() - w) {
    char_x = w;
    char_y += vert;
    if (char_y > height() - vert) {
      char_y = 0;
    }

    x = 0;
    y = char_y;

  } else {
    char_x += w;
  }

  // construct the char into the buffer
  for (j=0; j<vert; j++) {  //  vert line
    for (i=0; i<hor; i++) {   //  horz line
      z =  zeichen[bpl * i + ((j & 0xFFF8) >> 3)+1];
      b = 1 << (j & 0x07);
      if (( z & b ) == 0x00) {
        pixel(x+i,y+j,0);
      } else {
        pixel(x+i,y+j,1);
      }

    }
  }
}

void sharp_mlcd::set_font(unsigned char* f)
{
  font = f;
}

void sharp_mlcd::set_auto_up(unsigned int up)
{
  if (up) {
    auto_up = 1;
  } else {
    auto_up = 0;
  }
}

unsigned int sharp_mlcd::get_auto_up(void)
{
  return (auto_up);
}

void sharp_mlcd::print_bm(Bitmap bm, int x, int y, int color = 1)
{
  int h,v,b;
  char d;

  for(v=0; v < bm.ySize; v++) {   // lines
    for(h=0; h < bm.xSize; h++) { // pixel
      if(h + x >= width()) break;
      if(v + y >= height()) break;
      d = bm.data[bm.Byte_in_Line * v + ((h & 0xFFF8) >> 3)];
      b = 0x80 >> (h & 0x07);
      if((d & b) == 0) {
        pixel(x+h,y+v,!color);
      } else {
        pixel(x+h,y+v,color);
      }
    }
  }
}