Lightweight proportional text library for C12832 LCD. Easy to modify, fast, robust and compact. Nice font, good for text driven menus, messages, etc. Fell free to use and modify in any projects.

Dependents:   app-board-lcd128

Documentation will be here later.

Usage sample:

Import programapp-board-lcd128

Sample usage of lightweight C12832 LCD library

lcd128lib.cpp

Committer:
medvdv
Date:
2017-01-14
Revision:
7:d73d65360196
Parent:
6:5cd32671a837

File content as of revision 7:d73d65360196:

//
// MBED Application Board
// Lightweight C12832 LCD library
// 2014, Alexander Medvedev, @medvdv
//

#include "mbed.h"

#include "lcd128lib.h"
#include "lcd128font8.h"

// 
// lcd128 class implementation
//

// SPI writer with command / data switch

void lcd128::write(unsigned char data, bool cmd)
{
    a0 = cmd ? 0 : 1;
    cs = 0;
    spi.write(data);
    cs = 1;
}
 
// Constructor, SPI setup and defaults  

lcd128::lcd128(PinName mosi, PinName sclk, PinName p_a0, PinName p_cs, PinName p_rst):
spi(mosi, NC, sclk), rst(p_rst), cs(p_cs), a0(p_a0)
{
    // Setup SPI 
    spi.format(8, 3);
    spi.frequency(20000000);

    // Default font
    font.first_code = 32;
    font.glyphs_total = sizeof(font8widths) / sizeof(unsigned char);
    font.widths = font8widths;
    font.glyphs = font8chars;

    // Default drawing modes
    invert = false;
    bold = false;
    underline = false;   
} 
 
// Inverting chars on / off

void lcd128::Invert(bool invert)
{
    this -> invert = invert;
}

// Bold mode (twice wide chars) on / off

void lcd128::Bold(bool bold)
{
    this -> bold = bold;
}

// Underline mode on / off

void lcd128::Underline(bool underline)
{
    this -> underline = underline;
}

// Reset LCD, configure defaults and contrast

void lcd128::Reset()
{
    a0  = 0;
    cs  = 1;
    rst = 0;
    
    wait_us(50); 
    
    rst = 1;
    
    wait_ms(5);

    write(0xae, true); 
    write(0xa2, true); 
    write(0xa0, true); 
    write(0xc8, true); 
    write(0x22, true); 
    write(0x2f, true); 
    write(0x40, true); 
        
    write(0xaf, true); 
    write(0x81, true); 
    write(0x17, true); 
    write(0xa6, true); 
    
    wait_ms(5);
    
    XY();
    Clear();
    Update();
}

// LCD power on / off

void lcd128::Power(bool power)
{
    if (!power) {
        write(0xae, true);
        write(0xa5, true);        
    } else {
        write(0xaf, true);
        write(0xa4, true);
    }
}

// Invert LCD on / off

void lcd128::InverseMode(bool invert)
{
    if (!invert) 
        write(0xa6, true);
    else        
        write(0xa7, true);
}

// Update buffer to LCD

void lcd128::Update()
{   
    unsigned char* p = buffer;
    
    for(int j=0; j<LCD_Y; j++) {
        write(0x00, true);
        write(0x10, true);
        write(0xb0+j, true);
        for(int i=0; i<LCD_X; i++) write(*p++, false);
    }
}

// Clear all buffer or just one row

void lcd128::Clear(int row)
{
    if(row == -1) 
        memset(buffer, 0, sizeof(buffer));
    else {
        if(row < 0) row = 0;
        if(row >= LCD_Y) row = LCD_Y - 1;  
        memset(buffer + row*LCD_X, 0, LCD_X);
    }
}

// Inverse all buffer or just one row

void lcd128::InverseRow(int row, unsigned char mask)
{
    if(row == -1) 
        for(int i=0; i < LCD_X*LCD_Y; i++) buffer[i] ^= mask;
    else {
        if(row < 0) row = 0;
        if(row >= LCD_Y) row = LCD_Y - 1;  
        for(int i=LCD_X*row; i < LCD_X*(row+1); i++) buffer[i] ^= mask;
    }
}

// Change current output position
// X in pixels [0..LCD_X-1]
// Y in rows   [0..LCD_Y-1]

void lcd128::XY(int x, int y)
{
    if (x<0)  x=0;
    if (x>(LCD_X-1)) x=LCD_X-1;
    if (y<0)  y=0;
    if (y>(LCD_Y-1)) y=LCD_Y-1;

    X = x;
    Y = y;
}

// Write one 8bit row 
// with inversion and XY update

void lcd128::Write(unsigned char byte)
{
    if (underline) byte |= 0x80;
    buffer[X+Y*LCD_X] = invert ? (~byte) : byte;
    
    if (++X > (LCD_X-1)) {
        X=0;
        if (++Y > (LCD_Y-1)) Y=0;
    }
}

// Write array of 8bit rows

void lcd128::Write(unsigned char * data, int size)
{
    for (int i=0; i<size; i++) Write(data[i]);
}

// Write array of 8bit rows, twice each

void lcd128::Write2(unsigned char * data, int size)
{
    for (int i=0; i<size; i++) {
        Write(data[i]);
        Write(data[i]);
    }
}

// Write 8bit row 'count' times

void lcd128::Write(unsigned char byte, int count)
{
    for (int i=0; i<count; i++) Write(byte);
}

// Draw one proportional font character
// Jump to next line if empty space is not enought

void lcd128::Character(char chr)
{
    if( chr < font.first_code ) return;
    if( chr > font.first_code + font.glyphs_total - 1 ) return;

    chr -= font.first_code;

    int width = font.widths[chr];

    if (bold) width*=2;

    if ((X + width) > (LCD_X-1)) {
        if (++Y > (LCD_Y-1)) Y = 0;
        XY(0,Y);
    }

    if (bold) {
        Write2( (unsigned char*) font.glyphs[chr], (int) font.widths[chr] );
        if (X != 0) {
            Write(0);
            Write(0);
        }
    } else {
        Write( (unsigned char*) font.glyphs[chr], (int) font.widths[chr] );
        if (X != 0) Write(0);
    }
}

// Calculate width of concrete character 
// takes into account bold setting 

int lcd128::CharacterWidth(char chr)
{
    if( chr < font.first_code ) return 0;
    if( chr > font.first_code + font.glyphs_total - 1 ) return 0;

    chr -= font.first_code;

    if (bold)
        return 2 * (font.widths[chr] + 1);
    else
        return font.widths[chr] + 1;
}

// Write string

void lcd128::String(char* str)
{
    while(*str) Character(*str++);
}

// Predict string width

int lcd128::StringWidth(char* str)
{
    int width = 0;

    while(*str) width += CharacterWidth(*str++);

    return width;
}

// Clear one line, 
// then write string from it's begin. 
// It can be inverted and aligned left, center and right

void lcd128::Row(int Y, char* str, bool inverse, int align)
{
    Clear(Y);
    XY(0, Y);
    switch(align) {
        case 1: 
            XY((LCD_X/2)-StringWidth(str)/2,Y); 
            break;
        case 2: 
            XY(LCD_X-StringWidth(str),Y); 
            break;
        case 0:
        default:     
            XY(0, Y);
            break;
    }
    
    String(str);
    if (inverse) InverseRow(Y);
}

// Draw progress bar
// fill from 0.0f to 1.0f

void lcd128::Bar(int width, float fill)
{
    if (width < 2) return;
    if (fill < 0.0) fill = 0.0;
    if (fill > 1.0) fill = 1.0;
    
    int a = (width - 2)*fill;
    int b = width - 2 - a;
    
    Write(LCD_BAR_B);
    Write(LCD_BAR_F, a);
    Write(LCD_BAR_U, b);
    Write(LCD_BAR_E);
}