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:
2014-02-05
Revision:
3:c0e409cda493
Parent:
2:fdea8ffb3c4f
Child:
4:1bd241d1fad0

File content as of revision 3:c0e409cda493:

//
// 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(char data, bool cmd)
{
    a0  =  cmd ? 0:1;
    cs  = 0;
    spi.write(data);
    cs  = 1;
}
 
// Constructor  
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);

    // Setup default font
    font.first_code = 32;
    font.glyphs_total = 128 - 32;
    font.widths = lcd_font8p_widths;
    font.glyphs = lcd_font8p;

    invert = false;
    bold = false;
    underline = false;   
} 
 
 // Start inverting chars
void lcd128::Invert(bool invert)
{
    this -> invert = invert;
}

// Start bold mode (repeat twice wide)
void lcd128::Bold(bool bold)
{
    this -> bold = bold;
}

// Start bold mode (repeat twice wide)
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 off
void lcd128::Power(bool power)
{
    if (!power) {
        write(0xae, true);
        write(0xa5, true);        
    } else {
        write(0xaf, true);
        write(0xa4, true);
    }
}

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

// Update buffer to LCD
void lcd128::Update()
{   
    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=0;
        
        memset(buffer+row*LCD_X, 0, LCD_X);
    }

    Update();
}

// 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(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(char* data, int size)
{
    for (int i=0; i<size; i++) Write(data[i]);
}

// Write array of 8bit rows, twice each
void lcd128::Write2(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(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( (char*) font.glyphs[chr], (int) font.widths[chr] );
        if (X != 0) {
            Write(0);
            Write(0);
        }
    } else {
        Write( (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 
void lcd128::Row(int Y, char* str)
{
    Clear(Y);
    XY(0, Y);
    String(str);
}

void lcd128::RowCenter(int Y, char* str)
{
    Clear(Y);
    XY((LCD_X/2)-StringWidth(str)/2,Y);
    String(str);
}   

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);

}