Library for Nuelectronics Nokia 3310/5110 LCD Display and joystick.
Dependents: N3310LCD_Demo FRDM_N3110LCD
Diff: N3310LCD.cpp
- Revision:
- 0:7efa6655d94b
- Child:
- 1:51961974fe55
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/N3310LCD.cpp Sun Mar 10 18:15:25 2013 +0000 @@ -0,0 +1,389 @@ +/* +* N3310LCD. A program to interface mbed with the nuelectronics +* Nokia 3310 LCD shield from www.nuelectronics.com. Ported from +* the nuelectronics Arduino code. +* +* Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk> +* +* Converted to a mbed library by Andrew D. Lindsay +* +* This file is part of N3310LCD. +* +* N3310LCD is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* N3310LCD is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with N3310LCD. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "N3310LCD.h" +#include "N3310Fonts.h" + +static unsigned char lcd_buffer[LCDROWMAX][LCDCOLMAX]; + +N3310LCD::N3310LCD (PinName mosi, PinName miso, PinName sck, + PinName ce, PinName dat_cmd, PinName lcd_rst, PinName bl_on) : + lcdPort(mosi, miso, sck), + ceWire(ce), dcWire(dat_cmd), rstWire(lcd_rst), blWire(bl_on) +{ +} + +void N3310LCD::init() +{ + // use default SPI format + lcdPort.format(8,0); + lcdPort.frequency(1000000); + + // lcd reset + wait_ms(1); + rstWire = 0; + wait_ms(1); + rstWire = 1; + + write(0x21, CMD); + write(0xc8, CMD); + write(0x06, CMD); + write(0x13, CMD); + write(0x20, CMD); + cls(); + write(0x0c, CMD); +} + +void N3310LCD::cls() +{ + write(0x0c, CMD); + write(0x80, CMD); + + for (int i = 0; i < 504; i++) + { + write(0, DATA); + } +} + +void N3310LCD::backlight(eBacklight state) +{ + // switch off/on back light + blWire = state; +} + +void N3310LCD::write(BYTE data, eRequestType req_type) +{ + // bring CS low for write + ceWire = 0; + + if (CMD == req_type) + dcWire = 0; + else // DATA + dcWire = 1; + + lcdPort.write(data); + + // write finished + ceWire = 1; +} + +void N3310LCD::locate(BYTE xPos, BYTE yPos) +{ + write(0x40 | yPos, CMD); // column + write(0x80 | xPos, CMD); // row +} + +void N3310LCD::drawBitmap(BYTE xPos, BYTE yPos, BYTE* bitmap, BYTE bmpXSize, BYTE bmpYSize) +{ + BYTE row; + + if (0 == bmpYSize % 8) + row = bmpYSize/8; + else + row = bmpYSize/8 + 1; + + for (BYTE n = 0; n < row; n++) + { + locate(xPos, yPos); + for(BYTE i = 0; i < bmpXSize; i++) + { + write(bitmap[i + (n * bmpXSize)], DATA); + } + yPos++; + } +} + +/* + * Name : clearBitmap + * Description : Clear an area of the screen, usually to blank out a + * previously drawn image or part of image. + * Argument(s) : x, y - Position on screen, x 0-83, y 1-6 + * size_x,size_y - Size of the image in pixels, + * size_y is multiple of 8 + * Return value : none + */ +void N3310LCD::clearBitmap( unsigned char x,unsigned char y, + unsigned char size_x,unsigned char size_y) + { + unsigned int i,n; + unsigned char row; + + row = (size_y % 8 == 0 ) ? size_y / 8 : size_y / 8 + 1; +// if (size_y % 8==0) +// row=size_y/8; +// else +// row=size_y/8+1; + + for (n=0;n<row;n++) { + locate(x,y); + for(i=0; i<size_x; i++) { + write( 0x00, DATA ); + } + y++; + } +} + +void N3310LCD::writeString(BYTE xPos, BYTE yPos, char* string, eDisplayMode mode) +{ + locate(xPos, yPos); + + while (*string) + { + writeChar(*string++, mode); + } +} + +void N3310LCD::writeStringBig(BYTE xPos, BYTE yPos, char* string, eDisplayMode mode) +{ + while (*string) + { + writeCharBig(xPos, yPos, *string , mode); + + if('.' == *string++) + xPos += 5; + else + xPos += 12; + } +} + +void N3310LCD::writeChar(BYTE ch, eDisplayMode mode) +{ + BYTE sendByte; + + unsigned char* pFont = (unsigned char*)font6_8; + ch -= 32; + + for (BYTE line = 0; line < 6; line++) + { + sendByte = *(pFont + ch*6 + line); + write((mode == NORMAL)? sendByte: (sendByte ^ 0xff) , DATA); + } +} + +void N3310LCD::writeCharBig(BYTE xPos, BYTE yPos, BYTE ch, eDisplayMode mode) +{ + BYTE sendByte; + + unsigned char* pFont = (unsigned char *) big_number; + + if('.' == ch) + ch = 10; + else if ('+' == ch) + ch = 11; + else if ('-' == ch) + ch = 12; + else + ch = ch & 0x0f; + + for(BYTE i = 0; i < 3; i++) + { + locate(xPos, yPos + i); + + for(BYTE j = 0; j < 16; j++) + { + sendByte = *(pFont + ch*48 + i*16 + j); + write((mode == NORMAL)? sendByte : (sendByte^0xff), DATA); + } + } +} + +/* + * Name : setPixel + * Description : Set a single pixel either on or off, update display buffer. + * Argument(s) : x,y - position, x = 0-83, y = 0-6 + * c - colour, either PIXEL_ON, PIXEL_OFF or PIXEL_XOR + * Return value : none + */ +void N3310LCD::setPixel( unsigned char x, unsigned char y, unsigned char c ) { +unsigned char value; +unsigned char row; + +// if( x < 0 || x >= LCDCOLMAX || y < 0 || y >= LCDPIXELROWMAX ) return; + if( x >= LCDCOLMAX || y >= LCDPIXELROWMAX ) return; + + row = y / 8; + + value = lcd_buffer[row][x]; + if( c == PIXEL_ON ) { + value |= (1 << (y % 8)); + } else if( c == PIXEL_XOR ) { + value ^= (1 << (y % 8)); + } else { + value &= ~(1 << (y % 8)); + } + + lcd_buffer[row][x] = value; + + locate (x,row); + write(value, DATA); +} + + +/* + * Name : drawLine + * Description : Draws a line between two points on the display. + * Argument(s) : x1, y1 - Absolute pixel coordinates for line origin. + * x2, y2 - Absolute pixel coordinates for line end. + * c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR + * Return value : none + */ +void N3310LCD::drawLine(unsigned char x1, unsigned char y1, + unsigned char x2, unsigned char y2, unsigned char c) { + int dx, dy, stepx, stepy, fraction; + + /* Calculate differential form */ + /* dy y2 - y1 */ + /* -- = ------- */ + /* dx x2 - x1 */ + + /* Take differences */ + dy = y2 - y1; + dx = x2 - x1; + + /* dy is negative */ + if ( dy < 0 ) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + + /* dx is negative */ + if ( dx < 0 ) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + + dx <<= 1; + dy <<= 1; + + /* Draw initial position */ + setPixel( x1, y1, c ); + + /* Draw next positions until end */ + if ( dx > dy ) { + /* Take fraction */ + fraction = dy - ( dx >> 1); + while ( x1 != x2 ) { + if ( fraction >= 0 ) { + y1 += stepy; + fraction -= dx; + } + x1 += stepx; + fraction += dy; + + /* Draw calculated point */ + setPixel( x1, y1, c ); + } + } else { + /* Take fraction */ + fraction = dx - ( dy >> 1); + while ( y1 != y2 ) { + if ( fraction >= 0 ) { + x1 += stepx; + fraction -= dy; + } + y1 += stepy; + fraction += dx; + + /* Draw calculated point */ + setPixel( x1, y1, c ); + } + } +} + + +/* + * Name : drawRectangle + * Description : Draw a rectangle given to top left and bottom right points + * Argument(s) : x1, y1 - Absolute pixel coordinates for top left corner + * x2, y2 - Absolute pixel coordinates for bottom right corner + * c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR + * Return value : none + */ +void N3310LCD::drawRectangle(unsigned char x1, unsigned char y1, + unsigned char x2, unsigned char y2, unsigned char c){ + drawLine( x1, y1, x2, y1, c ); + drawLine( x1, y1, x1, y2, c ); + drawLine( x1, y2, x2, y2, c ); + drawLine( x2, y1, x2, y2, c ); +} + + +/* + * Name : drawFilledRectangle + * Description : Draw a filled rectangle given to top left and bottom right points + * just simply draws horizontal lines where the rectangle would be + * Argument(s) : x1, y1 - Absolute pixel coordinates for top left corner + * x2, y2 - Absolute pixel coordinates for bottom right corner + * c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR + * Return value : none + */ +void N3310LCD::drawFilledRectangle(unsigned char x1, unsigned char y1, + unsigned char x2, unsigned char y2, unsigned char c) { + for(int i=y1; i <= y2; i++ ) { + drawLine( x1, i, x2, i, c ); + } +} + + +/* + * Name : drawCircle + * Description : Draw a circle using Bresenham's algorithm. + * Some small circles will look like squares!! + * Argument(s) : xc, yc - Centre of circle + * r - Radius + * c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR + * Return value : None + */ +void N3310LCD::drawCircle(unsigned char xc, unsigned char yc, + unsigned char r, unsigned char c) { + int x=0; + int y=r; + int p=3-(2*r); + + setPixel( (uint8_t)(xc+x),(uint8_t)(yc-y), c); + + for(x=0;x<=y;x++) { + if (p<0) { + y=y; + p=(p+(4*x)+6); + } else { + y=y-1; + p=p+((4*(x-y)+10)); + } + + setPixel((uint8_t)(xc+x),(uint8_t)(yc-y), c); + setPixel((uint8_t)(xc-x),(uint8_t)(yc-y), c); + setPixel((uint8_t)(xc+x),(uint8_t)(yc+y), c); + setPixel((uint8_t)(xc-x),(uint8_t)(yc+y), c); + setPixel((uint8_t)(xc+y),(uint8_t)(yc-x), c); + setPixel((uint8_t)(xc-y),(uint8_t)(yc-x), c); + setPixel((uint8_t)(xc+y),(uint8_t)(yc+x), c); + setPixel((uint8_t)(xc-y),(uint8_t)(yc+x), c); + } +}