Skip to content

Instantly share code, notes, and snippets.

Created May 1, 2014 23:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/a9696856f6f83a27d662 to your computer and use it in GitHub Desktop.
Save anonymous/a9696856f6f83a27d662 to your computer and use it in GitHub Desktop.
/*
Adapted by: Davis Cook
Date: 4/29/2014
Using:
Nokia 5100 LCD Example Code
Graphics driver and PCD8544 interface code for SparkFun's
84x48 Graphic LCD.
https://www.sparkfun.com/products/10168
by: Jim Lindblom
adapted from code by Nathan Seidle and mish-mashed with
code from the ColorLCDShield.
date: October 10, 2013
license: Beerware. Feel free to use, reuse, and modify this
code as you see fit. If you find it useful, and we meet someday,
you can buy me a beer.
This all-inclusive sketch will show off a series of graphics
functions, like drawing lines, circles, squares, and text. Then
it'll go into serial monitor echo mode, where you can type
text into the serial monitor, and it'll be displayed on the
LCD.
This stuff could all be put into a library, but we wanted to
leave it all in one sketch to keep it as transparent as possible.
Hardware: (Note most of these pins can be swapped)
Graphic LCD Pin ---------- Arduino Pin
1-VCC ---------------- 5V
2-GND ---------------- GND
3-SCE ---------------- 7
4-RST ---------------- 6
5-D/C ---------------- 5
6-DN(MOSI) ---------------- 11
7-SCLK ---------------- 13
8-LED - 330 Ohm res -- 9
The SCLK, DN(MOSI), must remain where they are, but the other
pins can be swapped. The LED pin should remain a PWM-capable
pin. Don't forget to stick a current-limiting resistor in line
between the LCD's LED pin and Arduino pin 9!
*/
#include <SPI.h> // We'll use SPI to transfer data. Faster!
/* PCD8544-specific defines: */
#define LCD_COMMAND 0
#define LCD_DATA 1
/* 84x48 LCD Defines: */
#define LCD_WIDTH 84 // Note: x-coordinates go wide
#define LCD_HEIGHT 48 // Note: y-coordinates go high
#define WHITE 0 // For drawing pixels. A 0 draws white.
#define BLACK 1 // A 1 draws black.
/* Pin definitions:
Most of these pins can be moved to any digital or analog pin.
DN(MOSI)and SCLK should be left where they are (SPI pins). The
LED (backlight) pin should remain on a PWM-capable pin. */
const int scePin = 7; // SCE - Chip select, pin 3 on LCD.
const int rstPin = 6; // RST - Reset, pin 4 on LCD.
const int dcPin = 5; // DC - Data/Command, pin 5 on LCD.
const int sdinPin = 11; // DN(MOSI) - Serial data, pin 6 on LCD.
const int sclkPin = 13; // SCLK - Serial clock, pin 7 on LCD.
const int blPin = 9; // LED - Backlight LED, pin 8 on LCD.
/* Font table:
This table contains the hex values that represent pixels for a
font that is 5 pixels wide and 8 pixels high. Each byte in a row
represents one, 8-pixel, vertical column of a character. 5 bytes
per character. */
static const byte ASCII[][5] = {
// First 32 characters (0x00-0x19) are ignored. These are
// non-displayable, control characters.
{0x00, 0x00, 0x00, 0x00, 0x00} // 0x20
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 0x21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 0x22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 0x23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 0x24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 0x25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 0x26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 0x27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 0x28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 0x29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 0x2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 0x2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 0x2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 0x2d -
,{0x00, 0x60, 0x60, 0x00, 0x00} // 0x2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 0x2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 0x30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 0x31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 0x32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 0x33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 0x34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 0x35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 0x36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 0x37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 0x38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 0x39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 0x3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 0x3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 0x3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 0x3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 0x3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 0x3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 0x40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 0x41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 0x42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 0x43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 0x44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 0x45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 0x46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 0x47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 0x48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 0x49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 0x4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 0x4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 0x4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 0x4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 0x4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 0x4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 0x50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 0x51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 0x52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 0x53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 0x54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 0x55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 0x56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 0x57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 0x58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 0x59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 0x5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 0x5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 0x5c \
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 0x5d ]
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 0x5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 0x5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 0x5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 0x60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 0x61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 0x62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 0x63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 0x64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 0x65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 0x66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 0x67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 0x68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 0x69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 0x6a j
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 0x6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 0x6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 0x6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 0x6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 0x6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 0x70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 0x71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 0x72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 0x73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 0x74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 0x75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 0x76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 0x77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 0x78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 0x79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 0x7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 0x7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 0x7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 0x7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 0x7e ~
,{0x78, 0x46, 0x41, 0x46, 0x78} // 0x7f DEL
};
/* The displayMap variable stores a buffer representation of the
pixels on our display. There are 504 total bits in this array,
same as how many pixels there are on a 84 x 48 display.
Each byte in this array covers a 8-pixel vertical block on the
display. Each successive byte covers the next 8-pixel column over
until you reach the right-edge of the display and step down 8 rows.
To update the display, we first have to write to this array, then
call the updateDisplay() function, which sends this whole array
to the PCD8544.
Because the PCD8544 won't let us write individual pixels at a
time, this is how we can make targeted changes to the display. */
byte displayMap[LCD_WIDTH * LCD_HEIGHT / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,0)->(11,7) ~ These 12 bytes cover an 8x12 block in the left corner of the display
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,0)->(23,7)
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, 0x00, // (48,0)->(59,7)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (60,0)->(71,7)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (72,0)->(83,7)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,8)->(11,15)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,8)->(23,15)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // (24,8)->(35,15)
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, 0x00, // (60,8)->(71,15)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (72,8)->(83,15)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,16)->(11,23)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,16)->(23,23)
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, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (60,16)->(71,23)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (72,16)->(83,23)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,24)->(11,31)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,24)->(23,31)
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, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (60,24)->(71,31)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (72,24)->(83,31)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,32)->(11,39)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,32)->(23,39)
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, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (60,32)->(71,39)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (72,32)->(83,39)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (0,40)->(11,47)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (12,40)->(23,47)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (36,40)->(47,47)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (48,40)->(59,47)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (60,40)->(71,47)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* This array is the same size as the displayMap. We'll use it
as an example of how to draw a bitmap. */
char DigilentLogo[504] = {
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,
0x80, 0xE0, 0x30, 0x1C, 0x03, 0x01, 0x03, 0x0D, 0x19, 0x61, 0xC1, 0x01, 0x06, 0x1C, 0x30, 0xE0,
0x80, 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, 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, 0x80,
0x60, 0x18, 0x0C, 0x02, 0x03, 0xC0, 0x20, 0x18, 0x04, 0x02, 0x83, 0xE6, 0x3C, 0x40, 0xC1, 0x03,
0x0C, 0x1C, 0x70, 0xE0, 0x81, 0x02, 0x0C, 0x18, 0x60, 0x80, 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, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
0x30, 0x0C, 0x02, 0x01, 0x80, 0x60, 0x38, 0x0C, 0x03, 0x00, 0xC0, 0x70, 0x18, 0x06, 0x03, 0x00,
0x00, 0x00, 0x00, 0x03, 0x0C, 0x38, 0x60, 0x80, 0x03, 0x06, 0x1C, 0x60, 0x80, 0x01, 0x02, 0x0C,
0x10, 0x60, 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0,
0x0C, 0x06, 0x81, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x81, 0x60, 0x30, 0x3C, 0x26, 0x23, 0x21, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x26, 0x3C, 0x30, 0x20,
0x20, 0x23, 0x24, 0x38, 0x20, 0x00, 0x00, 0x03, 0x04, 0x18, 0x20, 0xC0, 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, 0x00,
0x00, 0x00, 0x07, 0x1F, 0x3C, 0x6F, 0x67, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x32, 0x36,
0x1F, 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, 0x00, 0x00, 0x1F, 0x11, 0x11, 0x0E, 0x00, 0x1D, 0x00, 0x0C, 0x52, 0x52,
0x3E, 0x00, 0x1D, 0x00, 0x1F, 0x00, 0x0C, 0x1A, 0x16, 0x04, 0x00, 0x1E, 0x02, 0x02, 0x1C, 0x00,
0x02, 0x0F, 0x12, 0x00, 0x00, 0x00, 0x00, 0x11, 0x1F, 0x11, 0x00, 0x1E, 0x02, 0x02, 0x1C, 0x00,
0x0C, 0x12, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
char GliderGun [] = {
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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0E, 0x11, 0x20, 0x20, 0x04, 0x11, 0x0E, 0x04, 0x00, 0x00, 0x03, 0x03, 0x04, 0x00, 0x0C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 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, 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,
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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
//this byte aray gives us a place to put the resutls obtained from calculating the new generation for the game of life
byte newGenerationMap[LCD_WIDTH * LCD_HEIGHT / 8] = {
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, 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, 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, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
};
void setup()
{
Serial.begin(9600);
lcdBegin(); // This will setup our pins, and initialize the LCD
setContrast(55); // Pretty good value, play around with it
clearDisplay(WHITE);
setBitmap(DigilentLogo);//Display the Digilent Logo on screen
//setBitmap(GliderGun);//Uncomment this to display a Glider Gun
updateDisplay(); // with displayMap untouched, SFE logo
delay(3000);
}
void loop()
{
calculateNextGeneration();
delay(50);
}
/////////////////////////////////////Conways Game of Life Functions/////////////////////////////////////////////
void calculateNextGeneration()
{//calculate the next iteration of conways game of life
int x, y;
//loop through every pixel and apply the rules of life
for(x = 0; x < LCD_WIDTH; x++)
{
for(y = 0; y < LCD_HEIGHT; y++)
{
applyRulesOfLife(x,y);
}
}
setBitmap((char*)newGenerationMap);//overwrite the old generation's bitmap(conatined in displayMap), with new generation's bitmap
updateDisplay();//display the new generation on the LCD
}
int getNumNeighbors(int x, int y)
{//check to see how many neighboring pixels are alive (i.e black)
int neighborCount = 0;
//check top left corner neighbor
if(getPixel(x-1, y-1))
{
neighborCount++;
}
//check top neighbor
if(getPixel(x, y-1))
{
neighborCount++;
}
//check top right corner neighbor
if(getPixel(x+1, y-1))
{
neighborCount++;
}
//check left neighbor
if(getPixel(x-1, y))
{
neighborCount++;
}
//check right neighbor
if(getPixel(x+1, y))
{
neighborCount++;
}
//check bottom left corner neighbor
if(getPixel(x-1, y+1))
{
neighborCount++;
}
//check bottom neighbor
if(getPixel(x, y+1))
{
neighborCount++;
}
//check bottom right corner neighbor.
if(getPixel(x+1, y+1))
{
neighborCount++;
}
return neighborCount;
}
void applyRulesOfLife(int x, int y)
{//This function applies the rules of life which are as follows
//1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
//2. Any live cell with two or three live neighbours lives on to the next generation.
//3. Any live cell with more than three live neighbours dies, as if by overcrowding.
//4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
int neighborNum;
neighborNum = getNumNeighbors(x, y);//get the number of neigbhors
//check to see if current cell is dead or alive
if(getPixel(x, y))//The cell is alive
{
if(neighborNum < 2)//apply rule 1
{
setPixel2(x,y,WHITE);//kill the cell
}
else if((neighborNum == 2) || (neighborNum == 3))//apply rule 2
{
setPixel2(x,y,BLACK);//ensure the cell lives to the next generation
}
else if( neighborNum > 3)//apply rule 3
{
setPixel2(x,y,WHITE);//kill the cell
}
}
else//The cell is dead
{
if(neighborNum == 3)//apply rule 4
{
setPixel2(x,y,BLACK);//create a new cell
}
}
}
////////////////////////////////////////////////LCD Functions/////////////////////////////////////////////////
void randomPixels()
{//Ranomly place a certain number of pixels
int numPixels = 1411;
clearDisplay(WHITE);//Clear the display before
randomSeed(analogRead(A0));
int x, y;
for(int i = 0; i < numPixels; i++)
{
x = random(0, 83);
y = random(0, 47);
setPixel(x, y);
}
}
//Get a pixels value from the displayMap
boolean getPixel(int x, int y)
{
//calculate torodial coordinates
if(x < 0)
{
x += LCD_WIDTH;
}
//wrap around for when x is outside LCD width
x %= LCD_WIDTH;
if(y < 0)
{
y += LCD_HEIGHT;
}
y %= LCD_HEIGHT;
int shift = y % 8;
boolean value;
byte b1 = displayMap[x + (y/8)*LCD_WIDTH];
value = 1&(b1 >> shift);
return value;
}
// Because I keep forgetting to put bw variable in when setting...
void setPixel(int x, int y)
{
setPixel(x, y, BLACK); // Call setPixel with bw set to Black
}
void clearPixel(int x, int y)
{
setPixel(x, y, WHITE); // call setPixel with bw set to white
}
// This function sets a pixel on displayMap to your preferred
// color. 1=Black, 0= white.
void setPixel(int x, int y, boolean bw)
{
// First, double check that the coordinate is in range.
if ((x >= 0) && (x < LCD_WIDTH) && (y >= 0) && (y < LCD_HEIGHT))
{
byte shift = y % 8;
if (bw) // If black, set the bit.
displayMap[x + (y/8)*LCD_WIDTH] |= 1<<shift;
else // If white clear the bit.
displayMap[x + (y/8)*LCD_WIDTH] &= ~(1<<shift);
}
}
// This function sets a pixel on newGenerationMap to your preferred
// color. 1=Black, 0= white.
void setPixel2(int x, int y, boolean bw)
{
// First, double check that the coordinate is in range.
if ((x >= 0) && (x < LCD_WIDTH) && (y >= 0) && (y < LCD_HEIGHT))
{
byte shift = y % 8;
if (bw) // If black, set the bit.
newGenerationMap[x + (y/8)*LCD_WIDTH] |= 1<<shift;
else // If white clear the bit.
newGenerationMap[x + (y/8)*LCD_WIDTH] &= ~(1<<shift);
}
}
// This function will draw a char (defined in the ASCII table
// near the beginning of this sketch) at a defined x and y).
// The color can be either black (1) or white (0).
void setChar(char character, int x, int y, boolean bw)
{
byte column; // temp byte to store character's column bitmap
for (int i=0; i<5; i++) // 5 columns (x) per character
{
column = ASCII[character - 0x20][i];
for (int j=0; j<8; j++) // 8 rows (y) per character
{
if (column & (0x01 << j)) // test bits to set pixels
setPixel(x+i, y+j, bw);
else
setPixel(x+i, y+j, !bw);
}
}
}
// setStr draws a string of characters, calling setChar with
// progressive coordinates until it's done.
// This function was grabbed from the SparkFun ColorLCDShield
// library.
void setStr(char * dString, int x, int y, boolean bw)
{
while (*dString != 0x00) // loop until null terminator
{
setChar(*dString++, x, y, bw);
x+=5;
for (int i=y; i<y+8; i++)
{
setPixel(x, i, !bw);
}
x++;
if (x > (LCD_WIDTH - 5)) // Enables wrap around
{
x = 0;
y += 8;
}
}
}
// This function will draw an array over the screen. (For now) the
// array must be the same size as the screen, covering the entirety
// of the display.
void setBitmap(char * bitArray)
{
for (int i=0; i<(LCD_WIDTH * LCD_HEIGHT / 8); i++)
displayMap[i] = bitArray[i];
}
// This function clears the entire display either white (0) or
// black (1).
// The screen won't actually clear until you call updateDisplay()!
void clearDisplay(boolean bw)
{
for (int i=0; i<(LCD_WIDTH * LCD_HEIGHT / 8); i++)
{
if (bw)
displayMap[i] = 0xFF;
else
displayMap[i] = 0;
}
}
// Helpful function to directly command the LCD to go to a
// specific x,y coordinate.
void gotoXY(int x, int y)
{
LCDWrite(0, 0x80 | x); // Column.
LCDWrite(0, 0x40 | y); // Row. ?
}
// This will actually draw on the display, whatever is currently
// in the displayMap array.
void updateDisplay()
{
gotoXY(0, 0);
for (int i=0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++)
{
LCDWrite(LCD_DATA, displayMap[i]);
}
}
// Set contrast can set the LCD Vop to a value between 0 and 127.
// 40-60 is usually a pretty good range.
void setContrast(byte contrast)
{
LCDWrite(LCD_COMMAND, 0x21); //Tell LCD that extended commands follow
LCDWrite(LCD_COMMAND, 0x80 | contrast); //Set LCD Vop (Contrast): Try 0xB1(good @ 3.3V) or 0xBF if your display is too dark
LCDWrite(LCD_COMMAND, 0x20); //Set display mode
}
/* There are two ways to do this. Either through direct commands
to the display, or by swapping each bit in the displayMap array.
We'll leave both methods here, comment one or the other out if
you please. */
void invertDisplay()
{
/* Direct LCD Command option
LCDWrite(LCD_COMMAND, 0x20); //Tell LCD that extended commands follow
LCDWrite(LCD_COMMAND, 0x08 | 0x05); //Set LCD Vop (Contrast): Try 0xB1(good @ 3.3V) or 0xBF if your display is too dark
LCDWrite(LCD_COMMAND, 0x20); //Set display mode */
/* Indirect, swap bits in displayMap option: */
for (int i=0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++)
{
displayMap[i] = ~displayMap[i] & 0xFF;
}
updateDisplay();
}
// There are two memory banks in the LCD, data/RAM and commands.
// This function sets the DC pin high or low depending, and then
// sends the data byte
void LCDWrite(byte data_or_command, byte data)
{
//Tell the LCD that we are writing either to data or a command
digitalWrite(dcPin, data_or_command);
//Send the data
digitalWrite(scePin, LOW);
SPI.transfer(data); //shiftOut(sdinPin, sclkPin, MSBFIRST, data);
digitalWrite(scePin, HIGH);
}
//This sends the magical commands to the PCD8544
void lcdBegin(void)
{
//Configure control pins
pinMode(scePin, OUTPUT);
pinMode(rstPin, OUTPUT);
pinMode(dcPin, OUTPUT);
pinMode(sdinPin, OUTPUT);
pinMode(sclkPin, OUTPUT);
pinMode(blPin, OUTPUT);
analogWrite(blPin, 255);
SPI.begin();
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
//Reset the LCD to a known state
digitalWrite(rstPin, LOW);
digitalWrite(rstPin, HIGH);
LCDWrite(LCD_COMMAND, 0x21); //Tell LCD extended commands follow
LCDWrite(LCD_COMMAND, 0xB0); //Set LCD Vop (Contrast)
LCDWrite(LCD_COMMAND, 0x04); //Set Temp coefficent
LCDWrite(LCD_COMMAND, 0x14); //LCD bias mode 1:48 (try 0x13)
//We must send 0x20 before modifying the display control mode
LCDWrite(LCD_COMMAND, 0x20);
LCDWrite(LCD_COMMAND, 0x0C); //Set display control, normal mode.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment