Nokia 5110 LCD screen driven by a BugOne

There are various LCD types : alphanumeric, graphical, colors, black and white… In this post I will use a cheap Nokia 5110 found once again on dx.com (or on eBay) for about 4-5€. This LCD screen has a resolution of 84 x 48 pixels, and is black and white only.

To test this LCD screen I decided to blink a picture (here Iron Man, see video at bottom) on the screen. To achieve this goal, I developed two things : a piece of code to drive the LCD screen with the BugOne and a computer program to generate data from a picture.

The development of the LCD screen driving commands started from both old code from a previous article and precious information from SkyDuino’s blog. The LCD breadboard contains 8 pins, 5 of which need to be driven from the controller (add one more if you want to drive the back light). The full code is available in the archive at the end of the article and provide a simple API to use the LCD.

#define RESET B,0
#define DC    B,1
#define DIN   B,2
#define CLK   B,3
#define SCE   B,4

// --- PCD8544 COMMANDS ---
#define CMD_NOOP    0x00
#define CMD_FS      0x20
#define CMD_SET_Y   0x40
#define CMD_SET_X   0x80

#define CMD_DISPLAY_BLANK   0x08
#define CMD_DISPLAY_NORMAL  0x0C
#define CMD_DISPLAY_BLACK   0x0B
#define CMD_DISPLAY_INVERSE 0x0D

#define CMD_FS_CHIP_ON  0x00
#define CMD_FS_CHIP_OFF 0x04
#define CMD_FS_H_ALIGN  0x00
#define CMD_FS_V_ALIGN  0x02
#define CMD_FS_BASIC    0x00
#define CMD_FS_EXTENDED 0x01

#define CMD_EXT_TEMP 0x04
#define CMD_EXT_BIAS 0x10
#define CMD_EXT_VOP  0x80

#include <avr/io.h>

extern void pcd_init();
extern void pcd_write_cmd(uint8_t data);
extern void pcd_write_data(uint8_t data);
extern void pcd_goto(uint8_t x, uint8_t y);
extern void pcd_img(uint8_t * img);
extern void pcd_clear();
extern void pcd_black();

I did try to provide an exhaustive list of commands, however, I used hex codes furnished on Skyduino’s blog which allow to initialize the contrast.

void pcd_init() {
  drive(RESET);
  drive(DC);
  drive(CLK);
  drive(DIN);
  drive(SCE);
  clr_output(CLK);
  set_output(SCE);
  reset();
  clr_output(SCE);

  pcd_write_cmd(0x21);
  pcd_write_cmd(0xBF);
  pcd_write_cmd(0x04);
  pcd_write_cmd(0x14);
  pcd_write_cmd(0x20);
  pcd_write_cmd(0x0C);
}

Writing a command or data to the display is differentiated by the state of the D/C pin. Thus data transfer (Most Significant Bit first) is common for pcd_write_cmd and pcd_write_data.

static void pcd_write(uint8_t data) {
  uint16_t mask = 0x80;
  uint8_t i;
  for (i = 0; i < 8; i++) {
    if ((data & mask) == mask) {
      set_output(DIN);
    } else {
      clr_output(DIN);
    }
    clk();
    mask >>= 1;
  }
}

void pcd_write_cmd(uint8_t data) {
  clr_output(DC);
  pcd_write(data);
}

void pcd_write_data(uint8_t data) {
  set_output(DC);
  pcd_write(data);
}

Now, let see the code allowing to blank the screen, paint it all in black or display an image. Code is pretty simple as shown above.

void pcd_goto(uint8_t x, uint8_t y) {
  pcd_write_cmd(CMD_SET_X | x);
  pcd_write_cmd(CMD_SET_Y | y);
}

void pcd_clear() {
  pcd_goto(0, 0);
  uint16_t i = 0;
  for (i = 0; i < 84*48/8; i++) {
    pcd_write_data(0x00);
  }
}

void pcd_black() {
  pcd_goto(0, 0);
  uint16_t i = 0;
  for (i = 0; i < 84*48/8; i++) {
    pcd_write_data(0xFF);
  }
}

void pcd_img(uint8_t * img) {
  pcd_goto(0, 0);
  uint16_t i = 0;
  for (i = 0; i < 504; i++) {
    pcd_write_data(img[i]);
  }
}

Finally, I wrote some Java code to generate hex data from a picture file. One important thing to notice is that the screen has 6 lines of 84×8 pixels. Thus parsing of the picture must be done carefully, see partial code below.

for (int y = 0; y < image.getHeight(); y += 8) {
	for (int x = 0; x < image.getWidth(); x++) {
		int b = 0;
		for (int k = 0; k < 8; k++) {
			int pixel = image.getRGB(x, y + k);
			output.setRGB(x, y + k, pixel);
			if (Color.BLACK.equals(new Color(pixel))) {
				b += Math.pow(2, k);
			}
		}
		System.out.print(IOTools.toHexByte(b) + ", ");
	}
}

The result is shown in the following video. I took an Iron Man picture as a test, just because I saw the third movie few days before writing this article 🙂 All the code I developed is available in the archive after the video. A jar version of the converter is also provided. To launch it, use :

java -jar lcd.jar file.png

Note that image file must be 84 x 48 pixels and that only black pixels are display on screen.

BugOne_Nokia_LCD.tar.gz

One Reply to “Nokia 5110 LCD screen driven by a BugOne”

Leave a Reply

Your email address will not be published. Required fields are marked *