Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

Arduino LCD playground | 12864 LCD library

12864 Graphics LCD library

12864 is an unofficial Arduino library that supports 12864 Graphic LCDs that use the ST7920 chip.

Download the library here:

https://playground.arduino.cc/uploads/Code/LCD12864.zip

////////////////////////////////////////////////////////

The library has been created by Markos Kyritsis, it is (of course) copyleft, which means you can take it and do whatever you want with it. But please, please, if you optimise it in any way, then contribute to the community and upload a copy for everyone else =D

Forum discussion here: http://forum.arduino.cc/index.php/topic,37687.html

////////////////////////////////////////////////////////

Here is a list of issues with the current version of the library:

  • Although you can draw graphics on both screens by issuing 1, or 2, when calling the RenderScreenBuffer method, you can't draw any object that starts in screen one, and ends in screen two. Its either all on the top screen, or on the bottom screen. You also HAVE to draw screen 2, before screen 1. Otherwise everything gets wiped.

Also, you can't draw a cropped part of the second screen yet (cropping is only supported on screen one).

  • It can switch from graphics to ASCII mode, but the value for the positioning is very strange. It seems non-linear (haven't had time to check this).

  • Its a little slow, but I managed to make a both a Pong game, and a side scroller for it, so its not that bad (You can download the pong game below). If you need to see the code for the side scroller, just send me a message on the forum above.

Now here is what it CAN do:

  • Draw Lines

  • Draw Rectangles

  • Draw Filled Rectangles

  • Draw Circles

  • Animation

  • Draw Bitmaps

  • ASCII (switch from graphics to ASCII)

Download the PONG game from here: https://playground.arduino.cc/uploads/Code/pongLCD.zip

Wiring:

  • EN = Arduino Pin 18
  • RS = Arduino Pin 17
  • RW = Arduino Pin 16
  • D7 = Arduino Pin 7
  • D6 = Arduino Pin 6
  • D5 = Arduino Pin 5
  • D4 = Arduino Pin 4
  • D3 = Arduino Pin 11
  • D2 = Arduino Pin 10
  • D1 = Arduino Pin 9
  • D0 = Arduino Pin 8
  • CSEL1 = Arduino Pin 14

You also need to connect a POT with 5V on one side, ground on the other, and 5V (perhaps with 150 Ohm resistance) + LCD Pin 19 to the wiper (middle one usually). Otherwise you won't see much.

If you need to change these values, you can find them in the LCD12864.h file. I tend to put CSEL in pin 12 in order to get the extra analog pin for joystick connections, etc...

Basic Commands:

All commands must follow an instance of the library. The instance is created automatically when you include the library, and has been named LCDA. So if you want to call Initialise(), you would call it by typing LCDA.Initialise();

setdelay(int newtime) Set a delay in ms, default is 80

Initialise() Init the LCD screen, clears the garbage on top and bottom screen, immediately sets it to graphics mode

Render() Call this after Initialise() to start the rendering process

Draw(bool t, int x, int y) This method enable or disables graphics mode

  • t (true = graphics mode, x can be anything, y can be anything)

  • t (false = ASCII mode, x is the position to place the character, ranging from 0 to 23. y doesn't do anything yet)

RenderScreenBuffer(int startX, int startY, int maxX, int maxY) Render a cropped rectangle of the screen buffer. Useful if you don't really want to render the whole screen (increases processing speed).

  • startX = starting X position of the cropped rectangle
  • startY = starting Y position of the cropped rectangle
  • maxX = ending X position of the cropped rectangle
  • maxY = ending Y position of the cropped rectangle

RenderScreenBuffer(int screen) Render the whole screen

  • screen (1 = top screen, 2 = bottom screen)

DumpScreenBuffer(int startX, int startY, int maxX, int maxY) Dump a cropped rectangle of the screen buffer. Useful if you don't really want to dump the whole screen (increases processing speed).

  • startX = starting X position of the cropped rectangle
  • startY = starting Y position of the cropped rectangle
  • maxX = ending X position of the cropped rectangle
  • maxY = ending Y position of the cropped rectangle

DumpScreenBuffer() Dump the whole screen

setPins(int tRS, int tRW, int tD7, int tD6, int tD5, int tD4, int tD3, int tD2, int tD1, int tD0) Pass a command directly to the screen

  • tRS = Register Set
  • tRW = Read/Write
  • tD7 = Data line 7
  • tD6 = Data line 6
  • tD5 = Data line 5
  • tD4 = Data line 4
  • tD3 = Data line 3
  • tD2 = Data line 2
  • tD1 = Data line 1
  • tD0 = Data line 0

Duplicate(bool x) Can duplicate what is shown in the first screen, onto the second screen, default is false

  • x (true = duplicate it)
  • x (false = don't duplicate it)

Drawing Commands:

DrawBrLine(int x0, int y0, int x1, int y1) Draw Bresenham line (straight line using the Bresenham algorithm)

  • x0 = starting X position, minimum value 0
  • y0 = starting Y position, minimum value 128
  • x1 = ending X position, max value 128
  • y1 = ending Y position, max value 160

DrawCircle(int x0, int y0, int radius) Draw Circle (uses the mid-point circle algorithm)

  • x0 = starting X position, minimum value 0
  • y0 = starting Y position, minimum value 128
  • r = radius (e.g. - 5)

DrawRectangle(int x0, int y0, int width, int height) Draw a nice rectangle =D

  • x0 = starting X position, minimum value 0
  • y0 = starting Y position, minimum value 128
  • width = horizontal size
  • height = vertical size

FillRectangle(int x0, int y0, int width, int height) Draw a nice filled rectangle

  • x0 = starting X position, minimum value 0
  • y0 = starting Y position, minimum value 128
  • width = horizontal size
  • height = vertical size

Please be careful, stay above the minimum value, and below the maximum value, otherwise program might crash.

Example

Lets try to draw a Circle, and a the number 012 on screen

First, we Initialise the LCD

LCDA.Initialise();

Let's delay a little bit

delay(500);

Now to start the rendering process (graphics on)

LCDA.Render();

Lets draw a circle

LCDA.DrawCircle(30,135,5);

The circle has been drawn to an off screen buffer, time to draw it on screen!

LCDA.RenderScreenBuffer(2); // lets draw it in the second screen

O.K. we said we need some characters in there as well. So lets enable ASCII mode and delay (we need at least 1 ms delay):

LCDA.Draw(false,4,0);

delay(1);

If we convert the characters '0', '1', and '2' we get the following 8 bit binary:

LCDA.setPins(1,0,0,0,1,1,0,0,0,0);

LCDA.setPins(1,0,0,0,1,1,0,0,0,1);

LCDA.setPins(1,0,0,0,1,1,0,0,1,0);

Now to wrap it all up, we set Draw back to true, if you don't do this the circle won't appear

LCDA.Draw(true,4,0);

More advanced stuff, messing around with the Sprite method (bitmaps and such)

Here is one way to draw a bitmap onto the screen:

  1. Convert a bitmap into monochrome (NOT GRAYSCALE)
  2. Use GIMP (which is open source) to save it as a C .h file
  3. Go to the LCD12864 directory (under hardware, in the Arduino directory), and edit the file named LCDSprite.h
  4. Open your .h file and copy everything from array static char header_data[]
  5. Paste the data into the array in LCDSprite.h (make sure you don't change the variable definition prog_char, followed by PROGMEM in the end
  6. Change the swidth and sheight variables to match the width and height of your sprite
  7. Save your changes
  8. Delete the LCD12864.o file (don't worry, it will get generated again once you compile it from the Arduino IDE)
  9. Pray to whatever deity you usually pray to, and compile

Now that you have successfully compiled your program, you can draw the image by using:

LCDA.DrawSprite(2,1); // 2 is the xPOS, 1 is the yPOS

delay(500); // you may or may not need the delay

LCDA.RenderScreenBuffer(1);

You can also create arrays like the char header_data[] in your sketch as well, and draw them manually (look at how this is done in the .cpp file). This is useful if you are creating a game, and need more than one image on the screen.

Future Work

The screen will work together with an SD card in order to exceed the current memory limits on the amount of bitmaps you can store. I plan to use the extra memory in order to create a simple yet relatively powerful (for home-made) hand held console. I hope to achieve this by merging my library with the SDuFat library. Coming soon!