new library for the EADOG LCD display from electronic assembly

Dependencies:   Fonts

EADOG.cpp

Committer:
sstaub
Date:
2016-09-22
Revision:
1:03129e57a003

File content as of revision 1:03129e57a003:

/* mbed library for the mbed Lab Board  128*32 pixel LCD
 * use ST7565R controller
 * Copyright (c) 2016 Stefan Staub
 * 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.
 */

#include "EADOG.h"
#include "mbed.h"
#include "stdio.h"
#include "Small_7.h"

EADOG::EADOG(PinName mosi, PinName sck, PinName reset, PinName a0, PinName cs, uint8_t type) : _spi(mosi, NC, sck), _reset(reset), _a0(a0), _cs(cs), _type(type), graphic_buffer() {
  if (_type == DOGM132) {
    width = 132;
    height = 32;
    graphic_buffer_size = 528;
    graphic_buffer = new uint8_t [graphic_buffer_size];
    }

  if (_type == DOGM128 || _type == DOGL128) {
    width = 128;
    height = 64;
    graphic_buffer_size = 1024;
    graphic_buffer = new uint8_t [graphic_buffer_size];
    }
    init();
  }

static void inline swap(int &a, int &b) {
  int c = a;
  a = b;
  b = c;
  }

void EADOG::display(uint8_t display) {
  if (display == ON) { // display on
    write_command(0xA4);
    write_command(0xAF);
    }
  if (display == OFF) { // display off
    write_command(0xAE);
    }

  if (display == SLEEP) {// display sleep
    write_command(0xA5);
    write_command(0xAE);
    }
  if(display == INVERT) { // invert display
    write_command(0xA7);
    }
  if(display == DEFAULT) { // set to normal display
    write_command(0xA6);
    }
  if (display == TOPVIEW) { // reverse orientation
    write_command(0xA0); // ADC normal
    write_command(0xC8); // reversed com31-com0
    update(); // update necessary
      }
  if (display == BOTTOM) { // normal orientation
    write_command(0xA1); // ADC reverse
    write_command(0xC0); // normal com0-com31
    update(); // update necessary
    }
  if (display == CONTRAST) {
    if (_type == DOGM132) {
      write_command(0x81); //  set contrast to default for dogm 128
      write_command(0x1F);
      }
    if (_type == DOGM128) {
      write_command(0x81); //  set contrast to default for dogm132
      write_command(0x16);
      }
    if (_type == DOGL128) {
      write_command(0x81); //  set contrast to default for dogl132
      write_command(0x10);
      }
    }
  }

void EADOG::display(uint8_t display, uint8_t value) {
  if (display == CONTRAST) {
    if (value < 64) {
      write_command(0x81); //  set contrast
      write_command(value & 0x3F);
      }
    }
  }

// write command to lcd controller
void EADOG::write_command(uint8_t command) {
  _a0 = 0;
  _cs = 0;
  _spi.write(command);
  _cs = 1;
  }

// write data to lcd controller
void EADOG::write_data(uint8_t data) {
  _a0 = 1;
  _cs = 0;
  _spi.write(data);
  _cs = 1;
  }

// reset and init the lcd controller
void EADOG::init() {
  _spi.format(8, 3);                 // 8 bit spi mode 3
  _spi.frequency(20000000);          // 19,2 Mhz SPI clock

  //DigitalOut _reset(A1);
  _a0 = 0;
  _cs = 1;
  _reset = 0;                        // display reset
  wait_us(50);
  _reset = 1;                       // end reset
  wait_ms(5);

  // Start Initial Sequence
  write_command(0x40); // display start line 0
  write_command(0xA1); // ADC reverse
  write_command(0xC0); // normal com0-com31
  write_command(0xA6); // display normal
  write_command(0xA2); // set bias 1/9 (duty 1/33)
  write_command(0x2F); // booster, regulator and follower on
  write_command(0xF8); // set internal booster to 3x/4x
  write_command(0x00);
  if (_type == DOGM132) {
    write_command(0x23); //  set contrast
    write_command(0x81);
    write_command(0x1F);
    }
  if (_type == DOGM128) {
    write_command(0x27); //  set contrast
    write_command(0x81);
    write_command(0x16);
    }
  if (_type == DOGL128) {
    write_command(0x27); //  set contrast
    write_command(0x81);
    write_command(0x10);
    }
  write_command(0xAC); // no indicator
  write_command(0x00);
  write_command(0xAF); // display on

  // clear and update LCD
  cls();
  auto_update = 1;              // switch on auto update
  locate(0, 0);
  font((unsigned char*)Small_7);  // standard font
  }

// update lcd
void EADOG::update() {
  //page 0
  write_command(0x00);      // set column low nibble 0
  write_command(0x10);      // set column hi  nibble 0
  write_command(0xB0);      // set page address  0
  _a0 = 1;

  for (int i = 0; i < width; i++) {
    write_data(graphic_buffer[i]);
    }

  // page 1
  write_command(0x00);      // set column low nibble 0
  write_command(0x10);      // set column hi  nibble 0
  write_command(0xB1);      // set page address  1
  _a0 = 1;

  for (int i = width; i < width * 2; i++) {
    write_data(graphic_buffer[i]);
    }

  //page 2
  write_command(0x00);      // set column low nibble 0
  write_command(0x10);      // set column hi  nibble 0
  write_command(0xB2);      // set page address  2
  _a0 = 1;

  for (int i = width * 2; i < width * 3; i++) {
    write_data(graphic_buffer[i]);
    }

  //page 3
  write_command(0x00);      // set column low nibble 0
  write_command(0x10);      // set column hi  nibble 0
  write_command(0xB3);      // set page address  3
  _a0 = 1;

  for (int i = width * 3; i < width * 4; i++) {
    write_data(graphic_buffer[i]);
    }

  if (_type == DOGM128 || _type == DOGL128) {
    //page 4
    write_command(0x00);      // set column low nibble 0
    write_command(0x10);      // set column hi  nibble 0
    write_command(0xB4);      // set page address  3
    _a0 = 1;

    for (int i = width * 4; i < width * 5; i++) {
      write_data(graphic_buffer[i]);
      }

    //page 5
    write_command(0x00);      // set column low nibble 0
    write_command(0x10);      // set column hi  nibble 0
    write_command(0xB5);      // set page address  3
    _a0 = 1;

    for (int i = width * 5; i < width * 6; i++) {
      write_data(graphic_buffer[i]);
      }

    //page 6
    write_command(0x00);      // set column low nibble 0
    write_command(0x10);      // set column hi  nibble 0
    write_command(0xB6);      // set page address  3
    _a0 = 1;

    for (int i = width * 6; i < width *7; i++) {
      write_data(graphic_buffer[i]);
      }

    //page 7
    write_command(0x00);      // set column low nibble 0
    write_command(0x10);      // set column hi  nibble 0
    write_command(0xB7);      // set page address  3
    _a0 = 1;

    for (int i = width * 7; i < width *8; i++) {
      write_data(graphic_buffer[i]);
      }
    }

  _cs = 0;

  }
void EADOG::update(uint8_t mode) {
  if (mode == MANUAL) auto_update = 0;
  if (mode == AUTO) auto_update = 1;
  }

// clear screen
void EADOG::cls() {
  memset(graphic_buffer, 0x00, graphic_buffer_size);  // clear display graphic_buffer
  update();
  }

// set one pixel in graphic_buffer
void EADOG::pixel(int x, int y, uint8_t color) {
  if (x > width - 1 || y > height - 1 || x < 0 || y < 0) return;
  if (color == 0) graphic_buffer[x + ((y / 8) * width)] &= ~(1 << (y % 8)); // erase pixel
  else graphic_buffer[x + ((y / 8) * width)] |= (1 << (y % 8));   // set pixel
  }

void EADOG::point(int x, int y, uint8_t colour) {
  pixel(x, y, colour);
  if (auto_update) update();
  }

// This function uses Bresenham's algorithm to draw a straight line.
void EADOG::line(int x0, int y0, int x1, int y1, uint8_t colour) {
  int dx =  abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
  int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
  int err = dx + dy, e2; /* error value e_xy */

  while(1) {
    pixel(x0, y0, 1);
    if (x0 == x1 && y0 == y1) break;
    e2 = 2 * err;
    if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
    if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
    }
  if (auto_update) update();
  }

void EADOG::rectangle(int x0, int y0, int x1, int y1, uint8_t colour) {
  uint8_t upd = auto_update;
  auto_update = 0;
  line(x0, y0, x1, y0, colour);
  line(x0, y1, x1, y1, colour);
  line(x0, y0, x0, y1, colour);
  line(x1, y0, x1, y1, colour);
  auto_update = upd;
  if (auto_update) update();
  }

void EADOG::fillrect(int x0, int y0, int x1, int y1, uint8_t colour) {
  if (x0 > x1) swap(x0, x1);
  if (y0 > y1) swap(y0, y1);
  for (int i = x0; i <= x1; i++) {
    for (int j = y0; j <= y1; j++) {
      pixel(i, j, colour);
      }
    }
  if (auto_update) update();
  }

void EADOG::roundrect(int x0, int y0, int x1, int y1, int rnd, uint8_t colour) {
  if (x0 > x1) swap(x0, x1);
  if (y0 > y1) swap(y0, y1);
  uint8_t upd = auto_update;
  auto_update = 0;
  int r = rnd;
  int x = -r, y = 0, err = 2 - 2 * r;
  line(x0 + rnd, y0, x1 - rnd, y0, colour);
  line(x0 + rnd, y1, x1 - rnd, y1, colour);
  line(x0, y0 + rnd, x0, y1 - rnd, colour);
  line(x1, y0 + rnd, x1, y1 - rnd, colour);
  do {
    pixel(x1 - rnd + y, y0 + x + rnd, 1); // 1 I. quadrant
    pixel(x1 - rnd - x, y1 + y - rnd, 1); // 2 IV. quadrant
    pixel(x0 + rnd - y, y1 - rnd - x, 1); // 3 III. quadrant
    pixel(x0 + rnd + x, y0 + rnd - y, 1); // 4 II. quadrant
    r = err;
    if (r <= y) err += ++y * 2 + 1;
    if (r > x || err > y) err += ++x * 2 + 1;
    } while (x < 0);
  auto_update = upd;
  if (auto_update) update();
  }

void EADOG::fillrrect(int x0, int y0, int x1, int y1, int rnd, uint8_t colour) {
  if (x0 > x1) swap(x0, x1);
  if (y0 > y1) swap(y0, y1);
  uint8_t upd = auto_update;
  auto_update = 0;
  int r = rnd;
  int x = -r, y = 0, err = 2 - 2 * r;
  for (int i = x0; i <= x1; i++) {
    for (int j = y0+rnd; j <= y1-rnd; j++) {
      pixel(i, j, colour);
      }
    }
  do {
    line(x0 + rnd - y, y0 + rnd + x, x1 - rnd + y, y0 + rnd + x, 1);
    line(x0 + rnd + x, y1 - rnd + y, x1 - rnd - x, y1 - rnd + y, 1);
    r = err;
    if (r <= y) err += ++y * 2 + 1;
    if (r > x || err > y) err += ++x * 2 + 1;
    } while (x < 0);
  auto_update = upd;
  if (auto_update) update();
  }

void EADOG::circle(int x0, int y0, int r, uint8_t colour) {
  int x = -r, y = 0, err = 2 - 2 * r;
  do {
    pixel(x0 + y, y0 + x, 1); // 1 I. quadrant
    pixel(x0 - x, y0 + y, 1); // 2 IV. quadrant
    pixel(x0 - y, y0 - x, 1); // 3 III. quadrant
    pixel(x0 + x, y0 - y, 1); // 4 II. quadrant
    r = err;
    if (r <= y) err += ++y * 2 + 1;
    if (r > x || err > y) err += ++x * 2 + 1;
    } while (x < 0);
  if (auto_update) update();
  }

void EADOG::fillcircle(int x0, int y0, int r, uint8_t colour) {
  uint8_t upd;
  upd = auto_update;
  auto_update = 0;
  int x = -r, y = 0, err = 2 - 2 * r;
  do {
    line(x0 - y, y0 + x, x0 + y, y0 + x, 1);
    line(x0 + x, y0 + y, x0 - x, y0 + y, 1);
    r = err;
    if (r <= y) err += ++y * 2 + 1;
    if (r > x || err > y) err += ++x * 2 + 1;
    } while (x < 0);
  auto_update = upd;
  if (auto_update) update();
  }

void EADOG::locate(uint8_t x, uint8_t y) {
  char_x = x;
  char_y = y;
  }

int EADOG::_putc(int value) {
  if (value == '\n') {    // new line
    char_x = 0;
    char_y = char_y + font_buffer[2];
    if (char_y >= height - font_buffer[2]) {
      char_y = 0;
      }
    }
  else {
    character(char_x, char_y, value);
    if (auto_update) update();
    }
  return value;
  }

int EADOG::_getc() {
      return -1;
  }

void EADOG::character(uint8_t x, uint8_t y, uint8_t c) {
  unsigned int hor, vert, offset, bpl, b;
  uint8_t *sign;
  uint8_t z, w;

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

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

  if (char_x + hor > width) {
    char_x = 0;
    char_y = char_y + vert;
    if (char_y >= height - font_buffer[2]) {
      char_y = 0;
      }
    }

  sign = &font_buffer[((c - 32) * offset) + 4]; // start of char bitmap
  w = sign[0];                          // width of actual char
  // construct the char into the font_graphic_buffer
  for (unsigned int j = 0; j < vert; j++) {  //  vert line
    for (unsigned int i = 0; i < hor; i++) {   //  horz line
      z =  sign[bpl * i + ((j & 0xF8) >> 3) + 1];
      b = 1 << (j & 0x07);
      if (( z & b ) == 0x00) {
        pixel(x+i, y+j, 0);
        }
      else {
        pixel(x+i, y+j, 1);
        }
      }
    }
  char_x += w;
  }


void EADOG::font(uint8_t *f) {
  font_buffer = f;
  }

void EADOG::bitmap(Bitmap bm, int x, int y) {
  int b;
  char d;

  for (int v = 0; v < bm.ySize; v++) {   // lines
    for (int 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 & 0xF8) >> 3)];
      b = 0x80 >> (h & 0x07);
      if ((d & b) == 0) {
        pixel(x+h, y+v, 0);
        }
      else {
        pixel(x+h, y+v, 1);
        }
      }
    }
    if (auto_update) update();
  }