This includes all known improvements from other people's spins on the Nokia library, including Alistair Popple's fix to the very poor contrast on newer LCD 6100 displays.

Fork of NokiaLCD by Iftekhar Choudhury

NokiaLCD.cpp

Committer:
simon
Date:
2010-06-09
Revision:
0:ff874f85ed33
Child:
1:8f005b0dcfa7

File content as of revision 0:ff874f85ed33:

/* mbed Nokia LCD Library
 * Copyright (c) 2007-2010, sford
 */

#include "NokiaLCD.h"

#include "mbed.h"

#define NOKIALCD_ROWS 16
#define NOKIALCD_COLS 16
#define NOKIALCD_WIDTH 130
#define NOKIALCD_HEIGHT 130
#define NOKIALCD_FREQUENCY 5000000

NokiaLCD::NokiaLCD(PinName mosi, PinName sclk, PinName cs, PinName rst, LCDType type)
        : _spi(mosi, NC, sclk)
        , _rst(rst)
        , _cs(cs) {

    _type = type;

    _row = 0;
    _column = 0;
    _foreground = 0x00FFFFFF;
    _background = 0x00000000;

    reset();
}

void NokiaLCD::reset() {

    // setup the SPI interface and bring display out of reset
    _cs = 1;
    _rst = 0;
    _spi.format(9);
    _spi.frequency(NOKIALCD_FREQUENCY);
    wait_ms(1);
    _rst = 1;
    wait_ms(1);

    _cs = 0;

    switch (_type) {
        case LCD6100:
            command(0xCA); // display control
            data(0);
            data(32);
            data(0);
            command(0xBB);
            data(1);
            command(0xD1); // oscillator on
            command(0x94); // sleep out
            command(0x20); // power control
            data(0x0F);
            command(0xA7); // invert display
            command(0x81); // Voltage control
            data(39);      // contrast setting: 0..63
            data(3);       // resistance ratio
            wait_ms(1);
            command(0xBC);
            data(0);
            data(1);
            data(4);
            command(0xAF);  // turn on the display
            break;
            
        case LCD6610:
            command(0xCA);    // display control
            data(0);
            data(31);
            data(0);
            command(0xBB);
            data(1);
            command(0xD1); // oscillator on
            command(0x94); // sleep out
            command(0x20); // power control
            data(0x0F);
            command(0xA7); // invert display
            command(0x81); // Voltage control
            data(39);      // contrast setting: 0..63
            data(3);       // resistance ratio
            wait_ms(1);
            command(0xBC);
            data(0);
            data(0);
            data(2);
            command(0xAF);  // turn on the display
            break;
            
        case PCF8833:
            command(0x11);  // sleep out
            command(0x3A);  // column mode
            data(0x05);
            command(0x36);  // madctl
            data(0x60);     // vertical RAM, flip x
            command(0x25);  // setcon
            data(0x30);// contrast 0x30
            wait_ms(2);
            command(0x29);//DISPON
            command(0x03);//BSTRON
            break;
    }

    _cs = 1;

    cls();
}

void NokiaLCD::command(int value) {
    _spi.write(value & 0xFF);
}

void NokiaLCD::data(int value) {
    _spi.write(value | 0x100);
}

void NokiaLCD::_window(int x, int y, int width, int height) {
    int x1 = x + 2;
    int y1 = y + 0;
    int x2 = x1 + width - 1;
    int y2 = y1 + height - 1;

    switch (_type) {
        case LCD6100:
        case LCD6610:
            command(0x15); // column
            data(x1);
            data(x2);
            command(0x75); // row
            data(y1);
            data(y2);
            command(0x5C); // start write to ram
            break;
        case PCF8833:
            command(0x2A);  // column
            data(x1);
            data(x2);
            command(0x2B); // row
            data(y1);
            data(y2);
            command(0x2C); // start write to ram
            break;
    }
}

void NokiaLCD::_putp(int colour) {
    int gr = ((colour >> 20) & 0x0F)
             | ((colour >> 8 ) & 0xF0);
    int nb = ((colour >> 4 ) & 0x0F);
    data(nb);
    data(gr);
}

const unsigned char FONT8x8[97][8] = {
    0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20
    0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // !
    0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // "
    0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // #
    0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $
    0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // %
    0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // &
    0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // '
    0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // (
    0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // )
    0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // *
    0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // +
    0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // ,
    0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // -
    0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // .
    0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash)
    0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30
    0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1
    0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2
    0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3
    0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4
    0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5
    0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6
    0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7
    0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8
    0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9
    0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // :
    0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ;
    0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // <
    0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // =
    0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // >
    0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ?
    0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40
    0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A
    0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B
    0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C
    0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D
    0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E
    0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F
    0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G
    0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H
    0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I
    0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J
    0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K
    0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L
    0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M
    0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N
    0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O
    0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50
    0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q
    0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R
    0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S
    0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T
    0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U
    0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V
    0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W
    0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X
    0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y
    0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z
    0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [
    0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash)
    0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ]
    0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _
    0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60
    0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a
    0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b
    0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c
    0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d
    0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e
    0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f
    0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g
    0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h
    0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i
    0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j
    0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k
    0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l
    0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m
    0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n
    0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o
    0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p
    0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q
    0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r
    0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s
    0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t
    0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u
    0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v
    0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w
    0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x
    0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y
    0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z
    0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // {
    0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // |
    0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // }
    0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~
    0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00
}; // DEL

void NokiaLCD::locate(int column, int row) {
    _column = column;
    _row = row;
}

void NokiaLCD::newline() {
    _column = 0;
    _row++;
    if (_row >= _rows) {
        _row = 0;
    }
}

int NokiaLCD::_putc(int value) {
    int x = _column * 8;  // FIXME: Char sizes
    int y = _row * 8;
    bitblit(x + 1, y + 1, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));

    _column++;

    if (_column >= NOKIALCD_COLS) {
        _row++;
        _column = 0;
    }

    if (_row >= NOKIALCD_ROWS) {
        _row = 0;
    }

    return value;
}

void NokiaLCD::cls() {
    fill(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT, _background);
    _row = 0;
    _column = 0;
}


void NokiaLCD::window(int x, int y, int width, int height) {
    _cs = 0;
    _window(x, y, width, height);
    _cs = 1;
}

void NokiaLCD::putp(int colour) {
    _cs = 0;
    _putp(colour);
    _cs = 1;
}

void NokiaLCD::pixel(int x, int y, int colour) {
    _cs = 0;
    _window(x, y, 1, 1);
    _putp(colour);
    _cs = 1;
}

void NokiaLCD::fill(int x, int y, int width, int height, int colour) {
    _cs = 0;
    _window(x, y, width, height);
    for (int i=0; i<width*height; i++) {
        _putp(colour);
    }
    _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT);
    _cs = 1;
}

void NokiaLCD::blit(int x, int y, int width, int height, const int* colour) {
    _cs = 0;
    _window(x, y, width, height);
    for (int i=0; i<width*height; i++) {
        _putp(colour[i]);
    }
    _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT);
    _cs = 1;
}

void NokiaLCD::bitblit(int x, int y, int width, int height, const char* bitstream) {
    _cs = 0;
    _window(x, y, width, height);
    for (int i=0; i<height*width; i++) {
        int byte = i / 8;
        int bit = i % 8;
        int colour = ((bitstream[byte] << bit) & 0x80) ? _foreground : _background;
        _putp(colour);
    }
    _window(0, 0, _width, _height);
    _cs = 1;
}

void NokiaLCD::foreground(int c) {
    _foreground = c;
}

void NokiaLCD::background(int c) {
    _background = c;
}

int NokiaLCD::width() {
    return NOKIALCD_WIDTH;
}

int NokiaLCD::height() {
    return NOKIALCD_HEIGHT;
}

int NokiaLCD::columns() {
    return NOKIALCD_COLS;
}

int NokiaLCD::rows() {
    return NOKIALCD_ROWS;
}