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
NokiaLCD.cpp
- Committer:
- simon
- Date:
- 2010-11-19
- Revision:
- 1:8f005b0dcfa7
- Parent:
- 0:ff874f85ed33
- Child:
- 3:ea0c085881f3
File content as of revision 1:8f005b0dcfa7:
/* 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); switch (_type) { case LCD6100: case PCF8833: for (int i=0; i<width*height; i++) { _putp(colour); } break; case LCD6610: for (int i=0; i<width*height/2; i++) { int r4 = (colour >> (16 + 4)) & 0xF; int g4 = (colour >> (8 + 4)) & 0xF; int b4 = (colour >> (0 + 4)) & 0xF; int d1 = (r4 << 4) | g4; int d2 = (b4 << 4) | r4; int d3 = (g4 << 4) | b4; data(d1); data(d2); data(d3); } break; } _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); switch (_type) { case LCD6100: case PCF8833: for (int i=0; i<width*height; i++) { _putp(colour[i]); } break; case LCD6610: for (int i=0; i<width*height/2; i++) { int r41 = (colour[i*2] >> (16 + 4)) & 0xF; int g41 = (colour[i*2] >> (8 + 4)) & 0xF; int b41 = (colour[i*2] >> (0 + 4)) & 0xF; int r42 = (colour[i*2+1] >> (16 + 4)) & 0xF; int g42 = (colour[i*2+1] >> (8 + 4)) & 0xF; int b42 = (colour[i*2+1] >> (0 + 4)) & 0xF; int d1 = (r41 << 4) | g41; int d2 = (b41 << 4) | r42; int d3 = (g42 << 4) | b42; data(d1); data(d2); data(d3); } break; } _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); switch (_type) { case LCD6100: case PCF8833: 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); } break; case LCD6610: for(int i=0; i<height*width/2; i++) { int byte1 = (i*2) / 8; int bit1 = (i*2) % 8; int colour1 = ((bitstream[byte1] << bit1) & 0x80) ? _foreground : _background; int byte2 = (i*2+1) / 8; int bit2 = (i*2+1) % 8; int colour2 = ((bitstream[byte2] << bit2) & 0x80) ? _foreground : _background; int r41 = (colour1 >> (16 + 4)) & 0xF; int g41 = (colour1 >> (8 + 4)) & 0xF; int b41 = (colour1 >> (0 + 4)) & 0xF; int r42 = (colour2 >> (16 + 4)) & 0xF; int g42 = (colour2 >> (8 + 4)) & 0xF; int b42 = (colour2 >> (0 + 4)) & 0xF; int d1 = (r41 << 4) | g41; int d2 = (b41 << 4) | r42; int d3 = (g42 << 4) | b42; data(d1); data(d2); data(d3); } break; } _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; }