*The code download is at the bottom.
Version 1.2 with considerable speed optimization and bug fixes is now available.
So I got my LCD a few days ago and started tweaking.
First thing I noticed in most libraries is that they use the Shiftout method and it is very slow.
Since I am a speed freak, I wanted to make something that will actually be fast.
And here is the result:
(The times displayed are in microseconds
The library uses Arduino's SPI bus. It assumes your arduino is running at 16MHz, and uses a /4 SPI (default) divider for an effective 4MHz SPI speed. This is the maximum speed the LCD supports.Schematic:
The library is configured to run on the Atmega168/328
(Uno, Mini, Nano, Duemilanove), but it can be reconfigured to run on any AVR based Arduino board.
By default it uses Digital Pins 8 - 13 (PORT B).
* Click to enlarge.
This LCD is a 3.3v device. The backlight requires 3.3v as well. My LCD has been pre-soldered to a breakout board with backlight resistors, so all I had to do is connect the LED pin to ground. Some LCDs may require 3.3v on their LED pin.
I use a CD4050 as a level shifter since my Arduino is a 5v device. The datasheet claims that the device is +5v tolerant on the signal lines, but I'm not taking any chances.
The CD4050's output voltage is the same as the VCC voltage provided, thus by driving it from the Arduino's 3.3v pin we get nice and clean 3.3v signals to the LCD.Code:
There are two versions of this library.
One utilizes a frame buffer, it uses 504 bytes of SRAM on your device, but it gives you additional flexibility and speed. It allows you to set an individual pixel on or off, it lets you draw a rectangle (empty or filled, empty is the default) and a horizontal or vertical lines (an attempt to draw a line at an angle will be ignored).
The second version doesn't use a frame buffer, therefore the memory footprint of this library is not very large. The lack of a frame buffer carries a small penalty in performance and only allows printing text and or bitmap data onto the screen. Nevertheless it is only just a little bit slower, so if you don't need the setPixel, writeRect and writeLine functions, save your RAM and use the non-frame buffered version.
The code may not be very pretty, as it's a rough beta version, but it's probably more than what I need for my plans for this LCD so I decided to share it with you.
It does not contain any protection against going out of the frame buffer (or the physical screen) so make sure you handle the screen borders properly.
What you need to know is this:
You can call the 'print' function like you do with the LiquidCrystal library or the Serial. It only supports ASCII characters 0x20 - 0x7F (32 - 127).
Call 'begin()' in your setup() method.Call renderAll() or renderString()
when using the Frame Buffer library, after you finish doing all your writing, call a render function. A call to print() returns a valid the number of bytes printed, therefore you can use this data to render a string much quicker than rendering the whole screen.
The setPixel method takes 'x', 'y' and value parameters (0 clears the pixel anything else sets it)
writeLine takes x1, y1, x2, y2. As I mentioned it only works on horizontal or vertical lines.
writeRect takes x, y, width, height, fill (true/false, default is false).
These last 3 methods assume the screen a 84x48 display.
is used for printing text, it looks at the LCD as display with 84 columns and 6 rows (banks). You can refer to the controllers data sheet for more information on this.
PCD8544_SPI lcd; // Declares a non-FrameBuffered instance.
PCD8544_SPI_FB lcd; // Declares a FrameBuffered instance.
// Call a render method after any print/write methods are called.
// For best perofrmance aggragate all writes before calling a render method.
void renderString(uint8_t x, uint8_t y, uint16_t length);
void setPixel(uint8_t x, uint8_t y, uint8_t value);
// WriteLine currently only supports horizontal and vertical lines.
void writeLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
void writeRect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, bool fill = false);
// Methods above are only available in the FrameBuffer version.
void gotoXY(uint8_t x, uint8_t y);
virtual size_t write(uint8_t uint8_t);
void writeBitmap(const uint8_t *bitmap, uint8_t x, uint8_t y, uint8_t width, uint8_t height);