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 Components

Original library is below link.
http://mbed.org/teams/components/code/C12832/
https://mbed.org/users/dreschpe/code/C12832_lcd/

I extended applicable LCD's not only 128 x 32 but also 128 x 48 and 128 x 64 type of SPI LCD using ST7565 controller.
I have checked AD-12864-SPI and AQM1248 LCD.
/media/uploads/kenjiArai/ad-12864-spi_12.png /media/uploads/kenjiArai/aqm12848_2.png

Import programLPC1114_SPI_LCD_ST7565family_test

Controller chip is ST7565

Revision:
19:871eed87d8ea
Child:
20:5b329c2a1ffe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ST7565_SPI_LCD.cpp	Sun Sep 21 01:04:42 2014 +0000
@@ -0,0 +1,593 @@
+/*
+    EXTEND for SPI interface LCD which is using ST7565 controller
+        Modified by Kenji Arai / JH1PJL  
+        http://www.page.sannet.ne.jp/kenjia/index.html
+        http://mbed.org/users/kenjiArai/
+            Started: September 20th, 2014
+            Revised: September 21st, 2014
+
+    original file: C12832.cpp
+    original Library name: C12832
+*/
+
+//---------- ORIGINAL Header ----------------------------------------------------
+/* 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
+
+#include "ST7565_SPI_LCD.h"
+#include "mbed.h"
+#include "stdio.h"
+#include "Small_7.h"
+
+#define BPP     1           // Bits per pixel
+
+#define DEBUG   0
+// Com
+#ifdef  DEBUG
+#define BAUD(x)             pcx.baud(x)
+#define GETC(x)             pcx.getc(x)
+#define PUTC(x)             pcx.putc(x)
+#define PRINTF(...)         pcx.printf(__VA_ARGS__)
+#define READABLE(x)         pcx.readable(x)
+#else
+#define BAUD(x)             {;}
+#define GETC(x)             {;}
+#define PUTC(x)             {;}
+#define PRINTF(...)         {;}
+#define READABLE(x)         {;}
+#endif
+#ifdef  DEBUG
+// com
+Serial      pcx(dp16,dp15);         // Communication with Host
+#endif
+
+ST7565::ST7565(PinName mosi, PinName sck,
+      PinName reset, PinName a0, PinName ncs, LCDType type, const char* name)
+    : GraphicsDisplay(name),_spi(mosi,NC,sck),_reset(reset),_A0(a0),_CS(ncs)
+{
+    initialize(type);
+}
+
+ST7565::ST7565(SPI& p_spi, PinName reset, PinName a0, PinName ncs, LCDType type, const char* name)
+    : GraphicsDisplay(name),_spi(p_spi),_reset(reset),_A0(a0),_CS(ncs)
+{
+    initialize(type);
+}
+
+void ST7565::initialize(LCDType type){
+    switch (type){
+        case LCD128x32:
+            lcd_width  = 128;
+            lcd_height = 32;
+            break;
+        case LCD128x48:
+            lcd_width  = 128;
+            lcd_height = 48;
+            break;
+        case LCD128x64:  
+            lcd_width  = 128;
+            lcd_height = 64;
+            break;
+        default:
+            lcd_width  = 128;
+            lcd_height = 64;
+    }
+    draw_mode = NORMAL;
+    char_x = 0;
+    lcd_reset();
+}
+
+int ST7565::width(){
+//    PRINTF("W:%d",lcd_width);
+    return(lcd_width);
+}
+
+int ST7565::height(){
+//    PRINTF("H:%d",lcd_height);
+    return(lcd_height);
+}
+
+void ST7565::invert(unsigned int o){
+    if(o == 0){
+        wr_cmd(0xA6);
+    } else {
+        wr_cmd(0xA7);
+    }
+}
+
+void ST7565::set_contrast(unsigned int o){
+    contrast = o;
+    wr_cmd(0x81);      //  set volume
+    wr_cmd(o & 0x3F);
+}
+
+unsigned int ST7565::get_contrast(void){
+    return(contrast);
+}
+
+// write command to lcd controller
+void ST7565::wr_cmd(unsigned char cmd){
+    _A0 = 0;
+    _CS = 0;
+    _spi.write(cmd);
+    _CS = 1;
+}
+
+// write data to lcd controller
+void ST7565::wr_dat(unsigned char dat){
+    _A0 = 1;
+    _CS = 0;
+    _spi.write(dat);
+    _CS = 1;
+}
+
+// reset and init the lcd controller
+void ST7565::lcd_reset(){
+    _spi.format(8,0);
+    _spi.frequency(10000000);   // 10 MHz SPI clock
+    _A0 = 0;
+    _CS = 1;
+    _reset = 0;                 // display reset
+    wait_us(50);
+    _reset = 1;                 // end reset
+    wait_ms(5);
+    // initialize sequence
+    wr_cmd(0xaf);     // display on
+    wr_cmd(0x2f);     // power control set
+    wr_cmd(0x81);     // set electronic volume mode
+    wr_cmd(0x00);     // electronic volume data 00-3f
+    wr_cmd(0x27);     // Volatge Regulator Internal Resister Ratio Set
+    wr_cmd(0xa2);     // LCD Bias Set ... 1/9 bias
+    wr_cmd(0xc8);     // Common Output Mode Select ... Reverse
+    wr_cmd(0xa0);     // ADC Select ... Norma
+    wr_cmd(0xa4);     // Display All Points ON/OFF ... normal
+    wr_cmd(0xa6);     // Display Normal/Reverse ... normal
+    wr_cmd(0xac);     // Static Indicator ... off
+    wr_cmd(0x00);     // off
+    wr_cmd(0x40);     // Display Strat Line Set ... 0
+    wr_cmd(0xe0);     // Write Mode Set
+    // clear and update LCD
+    memset(buffer,0x00,1024);  // clear display buffer
+    copy_to_lcd();
+    auto_up = 1;              // switch on auto update
+    // dont do this by default. Make the user call
+    //claim(stdout);           // redirect printf to lcd
+    locate(0,0);
+    set_font((unsigned char*)Small_7);  // standart font
+}
+
+// set one pixel in buffer
+void ST7565::pixel(int x, int y, int color){
+    // first check parameter
+    if(x > lcd_width || y > lcd_height || x < 0 || y < 0) return;
+    if(draw_mode == NORMAL) {
+        if(color == 0)
+            buffer[x + ((y/8) * 128)] &= ~(1 << (y%8));  // erase pixel
+        else
+            buffer[x + ((y/8) * 128)] |= (1 << (y%8));   // set pixel
+    } else { // XOR mode
+        if(color == 1)
+            buffer[x + ((y/8) * 128)] ^= (1 << (y%8));   // xor pixel
+    }
+}
+
+// update lcd
+void ST7565::copy_to_lcd(void){
+int i=0;
+    
+    // page 0
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB0);      // set page address  0
+    _A0 = 1;
+    for(i=0; i<128; i++) {
+        wr_dat(buffer[i]);
+    }
+    // page 1
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB1);      // set page address  1
+    _A0 = 1;
+    for(i=128; i<256; i++) {
+        wr_dat(buffer[i]);
+    }
+    // page 2
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB2);      // set page address  2
+    _A0 = 1;
+    for(i=256; i<384; i++) {
+        wr_dat(buffer[i]);
+    }
+    // page 3
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB3);      // set page address  3
+    _A0 = 1;
+    for(i=384; i<512; i++) {
+        wr_dat(buffer[i]);
+    }
+    if ((lcd_height == 48) || (lcd_height == 64)){
+        // page 4
+        wr_cmd(0x00);      // set column low nibble 0
+        wr_cmd(0x10);      // set column hi  nibble 0
+        wr_cmd(0xB4);      // set page address  4
+        _A0 = 1;
+        for(i=512; i<640; i++) {
+            wr_dat(buffer[i]);
+        }
+        // page 5
+        wr_cmd(0x00);      // set column low nibble 0
+        wr_cmd(0x10);      // set column hi  nibble 0
+        wr_cmd(0xB5);      // set page address  5
+        _A0 = 1;
+        for(i=640; i<768; i++) {
+            wr_dat(buffer[i]);
+        }
+    }   
+    if (lcd_height == 64){
+        // page 6
+        wr_cmd(0x00);      // set column low nibble 0
+        wr_cmd(0x10);      // set column hi  nibble 0
+        wr_cmd(0xB6);      // set page address  6
+        _A0 = 1;
+        for(i=768; i<896; i++) {
+            wr_dat(buffer[i]);
+        }
+        // page 7
+        wr_cmd(0x00);      // set column low nibble 0
+        wr_cmd(0x10);      // set column hi  nibble 0
+        wr_cmd(0xB7);      // set page address  7
+        _A0 = 1;
+        for(i=896; i<1024; i++) {
+            wr_dat(buffer[i]);
+        }
+    }
+    _CS = 0;
+}
+
+void ST7565::cls(void){
+    memset(buffer,0x00,1024);  // clear display buffer
+    copy_to_lcd();
+}
+
+void ST7565::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 ST7565::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 ST7565::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 ST7565::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 ST7565::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 ST7565::setmode(int mode){
+    draw_mode = mode;
+}
+
+void ST7565::locate(int x, int y){
+    char_x = x;
+    char_y = y;
+}
+
+int ST7565::columns(){
+    return width() / font[1];
+}
+
+int ST7565::rows(){
+    return height() / font[2];
+}
+
+void ST7565::line_clear(int y){
+unsigned int vert,j,i,x;
+
+    // read font parameter from start of array
+    vert = font[2];                      // get vert size of font
+    x = 0;
+    for (j=0; j<vert; j++) {  //  vert line
+        for (i=0; i<width(); i++) {  //  horz line
+            pixel(x+i,y+j,0);
+        }
+    }    
+}
+
+int ST7565::_putc(int value){
+    if (value == 0x0d) {    // new line
+        char_x = 0;
+        char_y = char_y + font[2];
+        if (char_y >= height() - font[2]){
+            char_y = 0;
+        }
+        line_clear(char_y);
+    } else {
+        character(char_x, char_y, value);
+        if(auto_up){ copy_to_lcd();}
+    }
+    return value;
+}
+
+void ST7565::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
+    if (char_x + hor > width()){
+        char_x = 0;
+        char_y = char_y + vert;
+        if (char_y >= height() - font[2]){
+            char_y = 0;
+        }
+    }
+    zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
+    w = zeichen[0];                          // width of actual char
+    // 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 & 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;
+    if(char_x >= (width() - hor)) {
+        char_x = 0;
+        char_y = char_y + vert;
+        if (char_y >= height() - font[2]){
+            char_y = 0;
+        }
+        line_clear(char_y);
+    }
+    //PRINTF("C:%d %d %d %d %d %d\r\n",offset,hor,vert,bpl,char_x,char_y);
+}
+
+void ST7565::set_font(unsigned char* f){
+    font = f;
+}
+
+void ST7565::set_auto_up(unsigned int up){
+    if(up){
+        auto_up = 1;
+    } else {
+        auto_up = 0;
+    }
+}
+
+unsigned int ST7565::get_auto_up(void){
+    return (auto_up);
+}
+
+void ST7565::print_bm(Bitmap bm, int x, int y){
+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 > 127){ break; }
+            if(v + y > 31){  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);
+            }
+        }
+    }
+}