Skip to content

Instantly share code, notes, and snippets.

@smittytone
Last active August 29, 2015 14:00
Show Gist options
  • Save smittytone/11397681 to your computer and use it in GitHub Desktop.
Save smittytone/11397681 to your computer and use it in GitHub Desktop.
Electric Imp example code to drive a Nokia 3310/5110 84 x 48 mono LCD
// Nokia 5110 control code for the imp
// Adapted by Tony Smith from a variety of sources:
// http://playground.arduino.cc/Code/PCD8544
// http://www.microsyl.com/index.php/2010/03/24/nokia-lcd-library/
// Assign the control pins to global variables
PIN_RST <- hardware.pin9;
PIN_CE <- hardware.pin8;
PIN_DC <- hardware.pin7;
PIN_DIN <- hardware.pin5;
PIN_CLK <- hardware.pin2;
PIN_BL <- hardware.pin1;
// Constants
const LCD_COMMAND = 0;
const LCD_DATA = 1;
const LCD_X = 84; // Screen's pixel width
const LCD_Y = 48; // Screen's pixel height
// ASCII is an array of Ascii characters, each defined by an
// array of five 8-bit values specifying a 5 x 8 pixel matrix
// Note: we pad characters in the code
ASCII <- [
[0x00, 0x00, 0x00, 0x00, 0x00], // 20
[0x00, 0x00, 0x5f, 0x00, 0x00], // 21 !
[0x00, 0x07, 0x00, 0x07, 0x00], // 22 "
[0x14, 0x7f, 0x14, 0x7f, 0x14], // 23 #
[0x24, 0x2a, 0x7f, 0x2a, 0x12], // 24 $
[0x23, 0x13, 0x08, 0x64, 0x62], // 25 %
[0x36, 0x49, 0x55, 0x22, 0x50], // 26 &
[0x00, 0x05, 0x03, 0x00, 0x00], // 27 '
[0x00, 0x1c, 0x22, 0x41, 0x00], // 28 (
[0x00, 0x41, 0x22, 0x1c, 0x00], // 29 )
[0x14, 0x08, 0x3e, 0x08, 0x14], // 2a *
[0x08, 0x08, 0x3e, 0x08, 0x08], // 2b +
[0x00, 0x50, 0x30, 0x00, 0x00], // 2c ,
[0x08, 0x08, 0x08, 0x08, 0x08], // 2d -
[0x00, 0x60, 0x60, 0x00, 0x00], // 2e .
[0x20, 0x10, 0x08, 0x04, 0x02], // 2f /
[0x3e, 0x51, 0x49, 0x45, 0x3e], // 30 0
[0x00, 0x42, 0x7f, 0x40, 0x00], // 31 1
[0x42, 0x61, 0x51, 0x49, 0x46], // 32 2
[0x21, 0x41, 0x45, 0x4b, 0x31], // 33 3
[0x18, 0x14, 0x12, 0x7f, 0x10], // 34 4
[0x27, 0x45, 0x45, 0x45, 0x39], // 35 5
[0x3c, 0x4a, 0x49, 0x49, 0x30], // 36 6
[0x01, 0x71, 0x09, 0x05, 0x03], // 37 7
[0x36, 0x49, 0x49, 0x49, 0x36], // 38 8
[0x06, 0x49, 0x49, 0x29, 0x1e], // 39 9
[0x00, 0x36, 0x36, 0x00, 0x00], // 3a :
[0x00, 0x56, 0x36, 0x00, 0x00], // 3b ;
[0x08, 0x14, 0x22, 0x41, 0x00], // 3c <
[0x14, 0x14, 0x14, 0x14, 0x14], // 3d =
[0x00, 0x41, 0x22, 0x14, 0x08], // 3e >
[0x02, 0x01, 0x51, 0x09, 0x06], // 3f ?
[0x32, 0x49, 0x79, 0x41, 0x3e], // 40 @
[0x7e, 0x11, 0x11, 0x11, 0x7e], // 41 A
[0x7f, 0x49, 0x49, 0x49, 0x36], // 42 B
[0x3e, 0x41, 0x41, 0x41, 0x22], // 43 C
[0x7f, 0x41, 0x41, 0x22, 0x1c], // 44 D
[0x7f, 0x49, 0x49, 0x49, 0x41], // 45 E
[0x7f, 0x09, 0x09, 0x09, 0x01], // 46 F
[0x3e, 0x41, 0x49, 0x49, 0x7a], // 47 G
[0x7f, 0x08, 0x08, 0x08, 0x7f], // 48 H
[0x00, 0x41, 0x7f, 0x41, 0x00], // 49 I
[0x20, 0x40, 0x41, 0x3f, 0x01], // 4a J
[0x7f, 0x08, 0x14, 0x22, 0x41], // 4b K
[0x7f, 0x40, 0x40, 0x40, 0x40], // 4c L
[0x7f, 0x02, 0x0c, 0x02, 0x7f], // 4d M
[0x7f, 0x04, 0x08, 0x10, 0x7f], // 4e N
[0x3e, 0x41, 0x41, 0x41, 0x3e], // 4f O
[0x7f, 0x09, 0x09, 0x09, 0x06], // 50 P
[0x3e, 0x41, 0x51, 0x21, 0x5e], // 51 Q
[0x7f, 0x09, 0x19, 0x29, 0x46], // 52 R
[0x46, 0x49, 0x49, 0x49, 0x31], // 53 S
[0x01, 0x01, 0x7f, 0x01, 0x01], // 54 T
[0x3f, 0x40, 0x40, 0x40, 0x3f], // 55 U
[0x1f, 0x20, 0x40, 0x20, 0x1f], // 56 V
[0x3f, 0x40, 0x38, 0x40, 0x3f], // 57 W
[0x63, 0x14, 0x08, 0x14, 0x63], // 58 X
[0x07, 0x08, 0x70, 0x08, 0x07], // 59 Y
[0x61, 0x51, 0x49, 0x45, 0x43], // 5a Z
[0x00, 0x7f, 0x41, 0x41, 0x00], // 5b [
[0x02, 0x04, 0x08, 0x10, 0x20], // 5c \
[0x00, 0x41, 0x41, 0x7f, 0x00], // 5d ],
[0x04, 0x02, 0x01, 0x02, 0x04], // 5e ^
[0x40, 0x40, 0x40, 0x40, 0x40], // 5f _
[0x00, 0x01, 0x02, 0x04, 0x00], // 60 `
[0x20, 0x54, 0x54, 0x54, 0x78], // 61 a
[0x7f, 0x48, 0x44, 0x44, 0x38], // 62 b
[0x38, 0x44, 0x44, 0x44, 0x20], // 63 c
[0x38, 0x44, 0x44, 0x48, 0x7f], // 64 d
[0x38, 0x54, 0x54, 0x54, 0x18], // 65 e
[0x08, 0x7e, 0x09, 0x01, 0x02], // 66 f
[0x0c, 0x52, 0x52, 0x52, 0x3e], // 67 g
[0x7f, 0x08, 0x04, 0x04, 0x78], // 68 h
[0x00, 0x44, 0x7d, 0x40, 0x00], // 69 i
[0x20, 0x40, 0x44, 0x3d, 0x00], // 6a j
[0x7f, 0x10, 0x28, 0x44, 0x00], // 6b k
[0x00, 0x41, 0x7f, 0x40, 0x00], // 6c l
[0x7c, 0x04, 0x18, 0x04, 0x78], // 6d m
[0x7c, 0x08, 0x04, 0x04, 0x78], // 6e n
[0x38, 0x44, 0x44, 0x44, 0x38], // 6f o
[0x7c, 0x14, 0x14, 0x14, 0x08], // 70 p
[0x08, 0x14, 0x14, 0x18, 0x7c], // 71 q
[0x7c, 0x08, 0x04, 0x04, 0x08], // 72 r
[0x48, 0x54, 0x54, 0x54, 0x20], // 73 s
[0x04, 0x3f, 0x44, 0x40, 0x20], // 74 t
[0x3c, 0x40, 0x40, 0x20, 0x7c], // 75 u
[0x1c, 0x20, 0x40, 0x20, 0x1c], // 76 v
[0x3c, 0x40, 0x30, 0x40, 0x3c], // 77 w
[0x44, 0x28, 0x10, 0x28, 0x44], // 78 x
[0x0c, 0x50, 0x50, 0x50, 0x3c], // 79 y
[0x44, 0x64, 0x54, 0x4c, 0x44], // 7a z
[0x00, 0x08, 0x36, 0x41, 0x00], // 7b [
[0x00, 0x00, 0x7f, 0x00, 0x00], // 7c |
[0x00, 0x41, 0x36, 0x08, 0x00], // 7d ]
[0x10, 0x08, 0x08, 0x10, 0x08], // 7e ~
[0x78, 0x46, 0x41, 0x46, 0x78], // 7f DEL
];
// IMP_GFX is an array of 84 x 5 8-bit values that are
// used to define an 84 x 48 pixel bitmap Electric Imp logo
IMP_GFX <- [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF8,
0xF8, 0x10, 0xC0, 0xF0, 0xF0, 0x30, 0x80, 0xC0,
0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFC, 0xFE,
0xFC, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0xF8, 0xFC, 0xFC, 0xFE, 0x7E, 0x7F, 0x3F, 0x3F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F,
0x3F, 0x7F, 0x7E, 0xFE, 0xFC, 0xFC, 0xF8, 0xFC,
0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF,
0xF8, 0xFE, 0xFF, 0xFF, 0xE1, 0xFC, 0xFF, 0xFF,
0x07, 0x00, 0x00, 0x00,
0x00, 0x18, 0x1E, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF,
0xFF, 0xEF, 0x0F, 0x0F, 0x1E, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0x3F,
0x0F, 0x73, 0xF1, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0,
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0,
0xF0, 0xF0, 0xF8, 0xF8, 0xF1, 0x63, 0x0F, 0x3F,
0xFF, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0x0F, 0xDF, 0xFF, 0xFF, 0xFF,
0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x07, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F,
0x3F, 0x7F, 0xFE, 0xF8, 0xE0, 0xC0, 0x00, 0x00,
0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8,
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x80, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03,
0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x83,
0x83, 0xC3, 0x43, 0x01, 0x00, 0x00, 0x00, 0xC0,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xF8,
0xF8, 0xF8, 0xF0, 0xFE, 0xFF, 0xFF, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3E,
0x3C, 0x7C, 0x7B, 0xF3, 0xF3, 0xE3, 0xE3, 0xE1,
0xE1, 0xC1, 0xC0, 0xC3, 0xCF, 0xDF, 0xFF, 0xFF,
0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0,
0xE0, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE3,
0xE1, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC, 0xFE, 0x7F,
0x3F, 0x1F, 0x07, 0x03, 0x00, 0x01, 0x81, 0xF1,
0xFF, 0xFF, 0x3F, 0x07, 0x03, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07,
0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07,
0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07,
0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
];
// MISC FUNCTIONS
function delay(value)
{
// Delay for ‘value’ milliseconds
local a = hardware.millis() + value;
while (hardware.millis() < a)
{
// NOP
}
}
// 5110 LCD FUNCTIONS
function LCDClear()
{
// Clear the LCD by writing zeros to the entire screen
for (local index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)
{
LCDWrite(LCD_DATA, 0x00);
}
// Position the cursor at the origin
LCDXY(0, 0);
}
function LCDXY(x, y)
{
// Position the cursor at column x, row y
// Origin is top left. x = 0-83. y = 0-5
LCDWrite(LCD_COMMAND, 0x80 | x);
LCDWrite(LCD_COMMAND, 0x40 | y);
}
function LCDBitmap(bitarray)
{
// Writes an array of 8-bit values to the LCD at
// the current cursor position
for (local index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)
{
LCDWrite(LCD_DATA, bitarray[index]);
}
}
function LCDCharacter(character)
{
// Writes a 5 x 8 character graphic from the ASCII array to the screen
// at the current cursor position. The integer parameter is the Ascii
// code of the character you want to print. The character is padded with
// one blank line to its left and another to its right.
LCDWrite(LCD_DATA, 0x00);
for (local index = 0 ; index < 5 ; index++)
{
LCDWrite(LCD_DATA, ASCII[character - 0x20][index]);
}
LCDWrite(LCD_DATA, 0x00);
}
function LCDString(string)
{
// Write a string of chracters to the LCD by taking each individual
// character and writing it with LCDCharacter(). The PCD8544 chip will
// move the cursor for you, wrapping the line and scrolling if necessary
foreach (character in string)
{
LCDCharacter(character);
}
}
function LCDWrite(data_or_command, data)
{
// There are two memory banks in the LCD: one for data, another for
// commands. Select the one you want by setting pin DC high (data) or
// low (command). Then signal the data/command transmission by setting
// pin CE low, writing the data/command, them setting CE high.
PIN_DC.write(data_or_command);
// Send the data
PIN_CE.write(0);
LCDWriteByte(data);
PIN_CE.write(1);
}
function LCDWriteByte(byteValue)
{
// Takes a byte of data and writes it out to the 5110 bit by bit,
// most significant bit first, least significant bit last.
// Each bit is signalled by setting pin CLK low and setting CLK
// high after the bit has been sent. The bit is sent on pin DIN.
for (local i = 8 ; i > 0 ; i--)
{
PIN_CLK.write(0);
PIN_DIN.write(byteValue & 0x80);
byteValue = byteValue << 1;
PIN_CLK.write(1);
}
}
function LCDLight(on_or_off)
{
// Turn the backlight on or off by passing a bool value
// The backlight takes 3.3V and can be either on or off
if (on_or_off)
{
PIN_BL.write(1);
}
else
{
PIN_BL.write(0);
}
}
function LCDInit()
{
// Configure the imp's pins
PIN_CE.configure(DIGITAL_OUT);
PIN_RESET.configure(DIGITAL_OUT);
PIN_DC.configure(DIGITAL_OUT);
PIN_DIN.configure(DIGITAL_OUT);
PIN_CLK.configure(DIGITAL_OUT);
PIN_BL.configure(DIGITAL_OUT);
// Reset the PCD8544 by setting RESET low then, after 10ms, back to high
PIN_RST.write(0);
imp.sleep(0.01);
PIN_RST.write(1);
// Switch off the backlight
LCDLight(false);
// Initialize the PCD8544 for use
// Send Function command (0x20) to select either
// basic command set (+0), or extended command set (+1)
LCDWrite(LCD_COMMAND, 0x21);
// Set LCD contrast command (0x80) using Vop
// Try 0xB1 (good @ 3.3V) or 0xBF if your display is too dark
LCDWrite(LCD_COMMAND, 0xB0);
// Set LCD temperature coefficient (0x04 + 0-3)
LCDWrite(LCD_COMMAND, 0x04);
// Set LCD bias voltage (0x10 + 0-7)
LCDWrite(LCD_COMMAND, 0x14);
// Send Function command (0x20) to select either
// horizontal screen addressing (+0) or vertical addressing (+2)
LCDWrite(LCD_COMMAND, 0x20);
// Set LCD display mode (0x08) plus
// 0 - All pixels clear (0x08)
// 1 - All pixels set (0x09)
// 4 - Normal video (0x0C)
// 5 - Inverse video (0x0D)
LCDWrite(LCD_COMMAND, 0x0C);
}
// PROGRAM FUNCTIONS
function show_stuff()
{
LCDClear();
// Flash the backlight
LCDLight(true);
delay (100);
LCDLight(false);
delay (100);
LCDLight(true);
delay (100);
LCDLight(false);
delay (100);
LCDLight(true);
delay (100);
LCDLight(false);
// Display Electric Imp logo
LCDBitmap(IMP_GFX);
// Position cursor at the start of the bottom row
LCDXY(0,5);
// Write a text string
LCDString("Electric Imp");
// Do it all again in 5 seconds
imp.wakeup(5.0, show_stuff);
}
// PROGRAM START
LCDInit();
show_stuff();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment