How to control 2 graphic LCDs with one Arduino

Raoul6391:
Hello

I plan to control 2 graphic LCD (http://www.sparkfun.com/products/710) using the KS0108 Graphics LCD library (Arduino Playground - GLCDks0108).

The library assumes you use one port (A,B or C) to connect one LCD.

I would like to know what I should modify in the library to use 2 LCDs?
Do I need to duplicate the library changing all functions name to address LCD 1 or LCD 2 (e.g. GLCD.ClearScreen1() for LCD 1 and GLCD.ClearScreen2() for LCD 2) ? Or is there any more elegant way to do it?
So far I am a user of the existing libraries but didn’t try myself to write one…
Thank you for your support.

Raoul.

Note: I am using a Mega 2560

Raul,
The library can run dual displays. I did this during the development of the new level code
that is in the current v3 beta version of the library.

I'd insert a photo of this running the demo sketches, but this forum
does not allow posting images.
(Yes I know it allows linking but I'm not going to upload it somewhere else)

There is a trick though. You must trick the library into "thinking" it is on larger display.
So rather than having 2 separate displays you change the config file to say it is
a 128x128 display with 4 chip selects.

The great thing is that it only takes 2 additional pins to do this.
Wiring up the displays is pretty simple as all the other pins,
D0-D7, EN, RW, DI, are all shared and wired together.

Then what you end up with is a 128x128 display is split across dual displays.
Not quite the same as 2 independent displays, but still very usable.
You can set up text areas that are limited to a single which makes text very easy.
For the graphics you have to be a bit careful not to transverse between the two
displays. And avoid things like GLCD.ClearScreen()

I have to go right now, but can elaborate further if you need more assistance.

--- bill

A bit of followup on the glcd library which is the next revision of the ks0108 library.
It was renamed to "glcd" because it now supports more than the ks0108.

The glcd v3 library is the "new and improved" ks0108 library.

With respect to device instantiation and runtime defining the pins,
this is not a simple task given the current code.

The current code has a single global instantiation "GLCD" and as you've seen defines the pins in a header file
rather than use runtime initialization.

There is a simple reason for this: Performance.
The standard arduino digital i/o routines are VERY slow and also only work on single pins.
By defining the pins in a header file the library code has access to them at compile.
Through much pre-processing magic (in avrio.h) and gcc compiler optimizations,
the final code for reading/writing pins can be usually reduced to a single AVR machine instruction.
The avrio.h code also optimizes across multiple pins so that depending on the AVR pins used,
things like reading the glcd data port can even be crushed down into a single instruction
vs having to call 8 digital read/write functions.
avrio is also smart enough to use nibble operations when possible, and will revert to individual
bit i/o if necessary.
If the pins were runtime declared, the performance would drop significantly.

With respect to the GLCD global instantiation. That was done for several reasons.
The main one being to try to simplify the user experience since it is automatically instantiated,
there is no runtime pin configuration, and usually the user does not need to configure
the pins in the header files. It was an attempt to offer a "it just works" out of box experience.
In that respect I think it has succeeded.

But also, when the code uses a global and only one of them, the code can also
be smaller, faster and use less RAM memory.

Speaking of memory, I did take another look at memory/RAM consumption.
There is zero initialized data. (which ends up in RAM with avr-gcc)
There is 53 bytes of static data,
There will be 12 bytes of RAM for each text area declared.

What can really eat up ram is the use of character strings.
While it might be assumed that strings land in flash (and they do),
they also will be copied to RAM.
That can be avoided if you declare your strings to put them in flash (program memory) and
then call glcd routines like Puts_P() Printf_P() to print them.

Attached are images of running the sketches supplied with the glcd v3 library
on dual ks0108 glcds using a teensy board.

--- bill

If you don't mind using an extra chip per display, you could have a lot of them. I did an article about driving graphical LCD displays using I2C or SPI here:

With I2C you could potentially have 8 displays (since you share the same 2 pins: SDA/SCL) and you can configure the chip to have up to 8 addresses. With SPI you can have as many displays as you can spare SS pins for (3 wires for MOSI/MISO/SCK plus one extra one for SS per display).

With a Mega you might not need to bother because you have some spare pins, but it is an idea.

True, adding an i2C i/o expander chip would offer a way to support several displays with very few pins
but not with the current glcd library implementation since the glcd library doesn't currently support
multiple instances.

--- bill

Bill,

On the topic of hardcoding pin selections, there may be some middle ground. I had run into a similar problem when creating the PrimeVfd library:Arduino Playground - PrimeVfd . digitalWrite() was nowhere near fast enough but I didn't want to limit the library to one pinout option and I wanted to support multiple displays.

What I did was to support a selection of hardcoded pin choices, with many choices intended to be used together with only the select pins differing. It is easy to expand the pin choices. The selection is specified as an enum and the constructor sets up some member variables based on that selection. This has negligible overhead for the most part. At the top of any method that is going to do something expensive, I copy the variable into a local register to help the compiler keep the variable in a register. When I looked at the assembly it looked pretty efficient.

I ran into one gotcha which may not even apply to glcd. PrimeVfd needs to clock out byte data which means setting a single output pin based on a bit value in a variable. If I hardcode to a pin on bit zero for example, then that becomes very easy. Even if it is not bit zero, it is fairly efficient if the amount of bit shifting is fixed. However, if the bit number is variable then it involves either a shift of unknown length at compile time (super expensive apparently) or an if-else operation. For this case however, it is possible to implement a branchless select which adds only a few instructions per bit.

This will burn some code space and add a few variables also. Overall, I felt the modest performance and memory hit was worth making the library more flexible, and IMO, a little easier to use.

  • Jayeson

Jayeson,
Its a really tough situation for using ks0108 glcd type devices on Arduinos,
particularly with the 168/328 based boards.

It is kind of the convergence of a perfect storm that makes things so difficult.

There are so many pins involved, that it is tough to pick a set of pins
for a default configuration or even a group of configurations.

Also, unlike character type lcds, the glcd software is
having to deal with 8192 bits of pixel data in a low level
interface. This means many thousands of times more i/o operations
to get things done over typical character lcds or intelligent glcds.
(and that is for a 128x64 glcd, with larger displays it is even more data)

The Arduino i/o interface is individual pin oriented.
So at 16mhz having 4us of overhead to deal with each individual pin vs 62.5 ns becomes
very significant, especially when looking at so many i/o operations.
With direct port i/o on the large arduino boards all 8 bits of a data byte
can be written in a single AVR machine cycle.

Another very painful thing is (IMHO) the poor choice of pin assignments Atmel chose for
the mega 8/16/168/328 AVRs. Because of the pin assignments, it is impossible to get
an 8 bit byte in a single AVR register on those processors when using the serial port
on those AVRs.
Even using nibbles across multiple ports can be challenging because of the
alternate port functions and the very limited number of pins on those AVRs.

Now toss in the inability to use a local frame buffer because of SRAM constraints,
(which means you may have to read remote glcd memory before you can write to update a pixel)
you can't really off load any of the processing to an interrupt routine as the glcd update
would make the ISR take too long (potentially several milliseconds),
and wanting to support user defined fonts of any size, and you quickly enter into a world
of having make many painful choices and sacrifices in order to get the functionality
working with reasonable performance across many different AVRs and different sized glcd displays.

The current implementation made many intentional design decisions and sacrifices
along the way to try to make the library easy to use and offer reasonably high performance
across all the arduino boards.
Ease of use was at the top of the list.

One thing that is in the current v3 implementation is that the user can use any arduino pin
for any glcd function. He just has to define these in a config file vs defining them runtime in his sketch.
This has allowed users to easily reconfigure the library to support freeing up pins for alternate functions.
The low level code has many complex macros and inline functions
under the hood that will automagically determine the best/fastest way to use AVR direct port i/o to
access the pins. For 8 bit operations it can reduce that down to a single AVR instruction or
use nibbles, individual pin i/o or any combination depending on the pins selected.
This optimization can't be done if the pin information is not known at compile time by the library
or if multiple instances are used.

Multiple instances was not an initial priority especially given the number of pins involved
for these types of displays.

That said, multiple instances might be something that gets a second look in the future
but in my view, in order to really support multiple instances, the interface needs to be
moved to some form of serial interface, SPI/I2C etc... vs individual control and data lines.
Which could be done very inexpensively using an i/o expander chip.

--- bill

I would have to go with Bill here. The simplest thing (and quite fast too) is to use the expander chip. My timings showed it works quite fast (especially if you use an SPI expander). For example, draw 96 characters of text in 54 ms. This is partly because you don't have to worry about generically setting individual bits, to send a byte of data to the LCD you simply SPI transfer that byte out, in itself quite a fast operation.

The library I wrote for the SPI/I2C expander supports multiple displays (link above). I doubt it supports all the stuff glcd does, but it may be enough for whatever you are trying to do.

Bill, Thanks for the information. Thanks for the work on the library also, it is quite excellent.

Once you get into using external chips, I think the challenge then becomes, what is that external chip. For not a whole lot more money than an I/O expander it is possible to by another AVR microcontroller and oscillator. That will free up a lot of resources on the Arduino. At this point, a shield starts to make sense as wiring up the displays can be a bit of a chore.

If I want lots of pins for cheap and don't mind dealing with all the wiring, my choice is to go with a Teensy(++), which is actually the only hardware I've used the graphics LCDs on.

Hi

Thank you again Bill for the time and for the (great) library.
It's abig help for users like me that are not at all software developers...

I started to work with 2 serial GLCD and I was stopped by the lack of performance, it was very slow and difficult to control overflows...
I tried GLCD V3 and the difference of performance is not only amazing but was solving most of the issues I had previously.
It was a great new for my project.

As I need 2 displays, I will try the aproach you proposed to "simulate" a larger 128X128 display.
I was wondering if it is possible make the library to "think" 256X64 instead of 128X128, that will make my life easier to rewrite code. Anyway it is not a big deal to adapt the code for 128X128...

Raoul

Yes you can easily create a larger display that is 256x64 instead of 128x128 if that works better.
It is just a matter of how you define the geometry and the chip selects.

It shouldn't be that difficult as you won't have to modify any code and
the the master ks0108 panel config files already have the necessary support for this.

There are 2 ways this can be done.
You can either use a autoconfig panel config file and then use pin configuration files.
OR you can use a manual panel config file.
When using a manual panel config file everything is in that one file including all the pins.
A manual panel config file will not select different pins depending on the board type.
Its pins are hard-coded/locked down.

The changes for either are basically the same.

====================
For a autoconfig panel config file

You can take a look at the ks0108-192x64_panel.h configuration file
to get an idea how this would work.

You can modify the autoconfig ks0108-Panel.h header file,
but I'd create a new header file by copying one of those
and use that one for this instead.

Then,
You will want to modify the DISPLAY_WIDTH define to 256

Then change the NBR_CHIP_SELECT_PINS to 4
Also (just for clarity if you run diags) alter the glcd_PanelConfigName string.
(it isn't really needed but might help avoid any confusion later)

This assumes you are going to use 2 glcd modules each with 2 chip selects.
(which is normal unless you want to add a decode chip so you can avoid having use 2 extra AVR pins)

You will then need to modify the master glcd_Config.h file to include
your new configuration file vs the original ks0108-Panel.h file.

==================
For a manual panel config file

Take a look at ks0108_Manual_Config.h
The same changes mentioned above apply.
The only difference is that the manual config file also has
the pins defined inside it vs the autoconfig panel config file references pin configuration files.

================

That's it as far as software configuration goes.
The code will figure out everything else at compile time.

The rest will be wiring up the panels.

Be careful about the current needs. Some backlights draw quite a bit of current and
if you are powering from a USB port,
You may have to limit the the backlight current a bit more than normal so
you don't draw too much power from the USB port.

You will then be able to use the text areas to limit text output to specific regions
of an individual display.
Or let the text span them both and wrap/scroll them both.

There are some special big number fonts provided if you want to display
numbers. They are really LARGE and are good for things like a clock or other
numeric type displays.

It will be a fun project.

--- bill

Bill
Thanks again.
I will try this week-end and will keep you posted.
Raoul

Hi Bill
I had a look on the files you indicated and identified the changes to do.
I would like to double check if it is correct (using autoconfig panel) to wire CSEL1 and CSEL2 of the second display to pin 32 and 31 of Arduino Mega?
Thank you.
Raoul.

Yes that is correct.
The CSEL1 and CSEL2 of the second glcd will connect to the pins for CSEL3 and CSEL4 in
the config file.

When I did my prototype, I used separate backlight resistors and separate contrast pots
for each glcd module as well.

One thing that might help wire things up is to use header pins on the glcd modules
(if you aren't already) and then use an old IDE cable. You can then plug the glcds into
the IDE cable (each one gets a row) and plug the cable into a proto board
where you can connect up the control and data lines and split off the other signals
as needed.

Be careful with the IDE cable though. Some are not straight through for all pins.
I forget which pins are funky but there is lots of information about it if you google around
a bit.

--- bill

Hi Bill.

It seems that it is not working as expected...

Let me explain what i did:

  1. I wired LCD1 according standard pin configuration and executed GLCDDiags: works fine
  2. I wired LCD2, connecting together D0 to D7 of both LCDs, then GLCDDiags failed for LCD1. It seems that Mega outputs are not strong enough to pilot 2 LCDs in parallel (the Mega is powered by an external 5V power supply).
  3. I decided to bufferized the signal before wiring D0 to D7 to LCD2 (using a IC I had : HTTP 301 This page has been moved). GLCDDiags worked well again with LCD1.
  4. I connected R_W, D_I and EN for LCD1 and LCD2 together. GLCDiags continued to work well with LCD1. LCD2 was displaying wrong data (normal as CSEL1 and CSEL2 were not connected).
  5. I connected CSEL1 and CSEL2 respectively to pin 32 and 31 of Mega. Same behaviour for LCD1 and LCD2.
  6. I compilled GLCDDiags with the modified files (copied below). GLCDDiags blocked in loop1 while initializing GLCD. In LCD 1 I could read on the half left Chip:1 64-127 and in the right half a bitmap pattern. Nothing displayed in LCD2.

Here below are the files I used:
glcd_Config.h

/*
 * glcd_Config.h - User specific configuration for Arduino GLCD library
 *
 * This file has been modified to automatically configure the library for using 
 * two LCDs 128x64 ks0108 panel as one LCd 256X64
 *
 * Use this file to select the active glcd configuration file
 * Then edit the selected panel file to configure parameters for that panel.
 *
 * This wiring is identical to the wiring used in the previous ks0108 library.
 * For Teensy devices the wiring selected matches the wiring documented on the Teensy website.
 *
 */

#ifndef glcd_CONFIG_H
#define glcd_CONFIG_H

 /*
  * You can select a configuration file by uncommenting one line to include the
  * the desired configuration file.
  *
  * Select 1 and only 1 configuration file.
  *
  * The "AutoConfig" configuration files will configure the library based on a set of
  * pre-customized configurations for the supported Arduino board type. 
  *
  * These configurations match the the panel configurations and wiring diagrams
  * in the library documentation based on the type of board selected in the Arduino IDE
  * and are compatible with wiring used in earlier versions of the ks0108 library
  *
  * NOTE: if you have a panel that has different dimensions than the distributed configuration, you can either
  * edit the supplied configuration file for that board type or create a fully custom configuration file.
  *
  * The auto configuration file (default is named  "config/ks0108_Panel.h") selects the appropriate board
  * pin configuration file based on the current board selection in the Arduino IDE.
  *   
  * The auto configuration panel configuration files can be found in the "config" directory, the naming is:
  *  "{PANELNAME}_Panel.h"
  * Where:
  *   {PANELNAME} is the glcd panel type. (for example, ks0108)
  *
  * The pin configuration files for each board type can also be found in the "config" directory, the naming is:
  *  "{PANELNAME}_{BOARDNAME}.h"
  * Where:
  *   {PANELNAME} is the glcd panel type. (for example, ks0108)
  *   {BOARDNAME} is the name of the board (as selected in the Arduino IDE).
  *
  * So for example, the auto configuration file name for a ks0108 panel
  * would be: "ks0108_Panel.h"
  * The ks0108 pin configuration file for a "Arduino" board would be: "ks0108_Arduino.h"
  * and the pin configuration file for a "Mega": "ks0108_Mega.h"
  * 
  */

/***********************************************************************************************************
 *
 * BETA TEST NOTE:
 *  - Does the autoconfig work correctly in your environment with your boards and displays?
 *  - Is the mechanism to make a custom configuration easy to use?
 *  - We want your comments and suggestions for making configuration easer, particularly for novices
 *
 * Additional "autoconfig" files can be created, there is an example for 192x64 panels in this distribution.
 * In the future there will be more for different panel types, like sed1520, ks0713, etc..
 * Not all custom configuration files that may be supplied in the release are included in the alpha distribution
 *
 ***********************************************************************************************************/


 /*
  * autoconfig includes - (comment this out if using manual configurations, see below)
  */
//#include "config/ks0108_Panel.h"          // automatically configure library for a ks0108 panel
//#include "config/ks0108-192x64_Panel.h"   // automatically configure library for a ks0108 192x64 panel
#include "config/ks0108-256X64_Panel.h"          // automatically configure library for a 256X64 panel

.....

And
ks0108-256X64_Panel.h

/*
 * ks0108-256X64_Panel.h - User specific configuration for Arduino GLCD library
 *
 * Use this file to set LCD panel parameters
 * This version is for a standard ks0108 display using 2 LCDs 128X56
 * This file uses a board specific pin assignment file based on the board selected in the IDE
 *
*/

#ifndef GLCD_PANEL_CONFIG_H
#define GLCD_PANEL_CONFIG_H

/*
 * define name for panel configuration
 */
#define glcd_PanelConfigName "ks0108 - two LCD 128X64"

/*********************************************************/
/*  Configuration for LCD panel specific configuration   */
/*********************************************************/
#define DISPLAY_WIDTH 256 // width using two 128X64 graphic LCD
#define DISPLAY_HEIGHT 64

// panel controller chips
#define CHIP_WIDTH     64  // pixels per chip
#define CHIP_HEIGHT    64  // pixels per chip

/*
 * the following is the calculation of the number of chips - do not change
 */
#define glcd_CHIP_COUNT ((DISPLAY_WIDTH + CHIP_WIDTH - 1)  / CHIP_WIDTH)

/*********************************************************/
/*  Chip Select Configuration                            */
/*********************************************************/

/*
 * Change the following define to match the number of Chip Select pins for this panel
 * Most panels use two pins for chip select,
 * but check your datasheet to see if a different number is required
 */
#define NBR_CHIP_SELECT_PINS   4 // this panel is using 4 CSEL pins (2XLCDs)
....

Any idea on how to debug?
Thank you for suporting.
Raoul.

Hi Bill

Maybe it can help to understand...

I wired in parallell CSEL1 and CSEL2 for both LCDs and executed GLCDDiags standard (to pilot one 128X64 LCD). In this case LCD1 is displaying fine while screnn in LCD2 is not fine.
GLCDDiags shows Tests PASSED.

I was wondering, as I am using a buffer for LCD2, this is introducing a delay on D0-D7, shall I need to tune delays?

Raoul.

You should not need any additional buffering. There should not be a loading issue.
The glcd will place very little load on the AVR pins and the AVR pins have quite a bit of "oomph".
This is a wiring issue or possibly a library code issue as I haven't specifically tested your exact configuration.
The main reason that I say it might be a library code issue is that currently the library
uses 8 bit values for x/y coordinates for speed. Because of this, the maximum
pixel value can be is 255.
There are some funny things that happen in the code as the display size gets to 256 pixels wide.
The code will actually not be able to address all 256 pixels across.
You will for sure lose the right most pixel all the way down.
There well may be some issues with the code as I have never tested the code with a 256 pixel wide
configuration and currently a pixel value of 255 is "magic" to the code internally.
We didn't put much effort into testing 256 pixel wide displays as we hadn't seen any panels this large
and this dual display mode is not something that many people will hook up.
You are off pioneering into some new territory.

Also keep in mind that incorrect wiring could potentially damage the glcds.
(unconnected wires are essentially the same as miswired wires)

On reason there can be issues is that if both glcds are not wired correctly, more than 1 glcd
or even more than 1 chip on a single glcd module
can attempt to drive the data bus at a time so you end up with bus collisions.

The way these modules work is that depending on the control line logic levels,
the ks0108 chips will do various things to the data bus.
The data bus is bi-directional. It must be shared between input and output so
all entities that are hooked up to the data bus must all be in agreement with
who should be using the data bus and in which direction.
In this setup, there are 5 entities (6 if you count the buffer chip)
that are potentially driving/accessing the data bus. The AVR, and four ks0108 chips (2 per glcd).
(Also the buffer chip if that is hooked up)

If a chip is selected, then it looks at the other control lines to see what to do
with the data bus. If the chip is not selected it floats its data bus pins to allow
something else to drive the bus. That could be another ks0108 chip on a glcd module
or it could be the host (AVR) depending on what is going on.
When selected, the chip will then look at the read/write line to see if the data bus
should be listened to (write rw=low) or driven (read rw=high).
The EN signal determines when the chip will drive the bus. If the rw pin is high,
the chip will drive the data bus pins as soon as EN goes high and will continue
to drive the bus as long as it remains selected, EN remains high and rw remains high.

When the data lines of both glcd modules were originally tied together, it sounds like none of the control lines
of the second glcd were hooked up. Because of this, the second glcd has floating control
lines. Floating inputs are not good. More than likely many if not all of the control lines float up to high.
If they all float high, then you would end up with the both ks0108 chips on the second glcd module
being selected (cs1+cs2 high) in read mode (r/w high) and EN high.
In this condition, both ks0108 chips on the second module
would attempt to drive the data bus all the time and that would
crash with the other module or even the AVR trying to drive the data bus.

Adding an external chip to drive the data bus for the AVR will not solve this.
Also, I'm not sure how the library code could work with that buffer chip.
(I'm betting that diags was failing).
I'm not sure how the buffer chip was hooked up but
since that buffer chip is not bi-directional and does not seem to have any output enables, it
will drive the bus all the time. Because of this, the AVR would not be able
to properly read data from the glcd memory as the buffer chip would be
driving the data bus at the same time as the ks0108 chips during read
operations.

========================
My suggestion is to remove the buffer chip and wire up the glcds directly
to the AVR pins.
Since these two glcd are being treated as a single glcd module to the software,
they both must be fully hooked up before either will work properly. It is just
like with a single glcd. If you left any wires not hooked up, the glcd will not work
properly. In this case if any wires on either glcd are not hooked up correctly,
it makes both fail.

Hook up d0-d7 lines together, hook the rw, en, di, lines together.
Then hook up each modules contrast and backlight pins separately.
All the CS lines must be hooked up and none can be shared.
(I can't see your mega pin configuration file but I'm assuming you didn't change it)
CS1 & CS2 from first module would pins 33,34
and CS1 & CS2 from second module would be pins 32,31

It should then work.
If not, run the diags sketch and capture the serial output
and past it here and we can diagnose from there.
If things are not working, then the serial output is a great tool
as it shows everything that the library is using to configure its low level
i/o code.

I'll work with you until we get this up and working to make sure that there is not
any issues in the actual library code, especially when the display
size is 256 pixels wide.

--- bill

Just a followup.
The library is working fine for the "dual display" 256x64 configuration.
I used my same 128x128 teensy++ setup and simply changed
the config file to make it 256x64 instead and everything works just fine.
I ran the diag and the glcdDemo sketches.

So you can definitely use the dual displays either way.
The only limitation is that when using 256x64 the library code will not
let you access the right most pixel.
It essentially creates a 255x64 display.

So if you want to access all the pixels you will have to run them vertically stacked
as 128x128 instead of horizontally stacked as 256x64.

--- bill

Hi Bill
Thanks a lot for your reply.
I will try following your recommendations tomorrow night (Central Europe Time).
And will keep you posted.
Raoul.

Bill

Thank you again for explaining how it works and not just giving tips to make it work… It helps to learn and react smarter in front of any issue.

I went back home for lunch time to do some testing.
You were right, library is working fine with a 256X64 configuration, and yes we loose the last column, meaning the real display is 255X64. I just executed GLCDDiags and some other simple programs I already have.

I confirm there is no need of additional buffering.

My mistake was a wrong wiring on CSEL1 and CSEL2, I confirm that the right configuration is (as it is stated in the file ks0108_Mega.h):

  • CS1 & CS2 from first module must be connected to pins 33, 34

  • CS1 & CS2 from second module must be connected to pins 32, 31.

I tried quickly to apply same methodology for a 128X128 configuration (modifying ks108_Panel.h to change HEIGHT to 128 and chip number to 4 and then GLCD_Config.h):

/*
 * ks0108-128X128_Panel.h - User specific configuration for Arduino GLCD library
 * Modification of ks0108_Panel.h to manage two 128X64 LCDs as one 128X128 LCD  
 * Use this file to set LCD panel parameters
 * This version is for a standard ks0108 display
 * This file uses a board specific pin assignment file based on the board selected in the IDE
 *
*/

#ifndef GLCD_PANEL_CONFIG_H
#define GLCD_PANEL_CONFIG_H

/*
 * define name for panel configuration
 */
#define glcd_PanelConfigName "Two 128X64 LCD in One LCD 128X128"

/*********************************************************/
/*  Configuration for LCD panel specific configuration   */
/*********************************************************/
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 128

// panel controller chips
#define CHIP_WIDTH     64  // pixels per chip
#define CHIP_HEIGHT    64  // pixels per chip

/*
 * the following is the calculation of the number of chips - do not change
 */
#define glcd_CHIP_COUNT ((DISPLAY_WIDTH + CHIP_WIDTH - 1)  / CHIP_WIDTH) 

/*********************************************************/
/*  Chip Select Configuration                            */
/*********************************************************/

/*
 * Change the following define to match the number of Chip Select pins for this panel
 * Most panels use two pins for chip select,
 * but check your datasheet to see if a different number is required
 */
#define NBR_CHIP_SELECT_PINS   4 // the number of chip select pins required for this panel
/*
 * glcd_Config.h - User specific configuration for Arduino GLCD library
 *
 * This file is shipped to automatically configure the library for a 
 * 128x128 ks0108 panel using the wiring described in the documentation.
 *
 * Use this file to select the active glcd configuration file
 * Then edit the selected panel file to configure parameters for that panel.
 *
 * This wiring is identical to the wiring used in the previous ks0108 library.
 * For Teensy devices the wiring selected matches the wiring documented on the Teensy website.
 *
 */

#ifndef glcd_CONFIG_H
#define glcd_CONFIG_H

 /*
  * You can select a configuration file by uncommenting one line to include the
  * the desired configuration file.
  *
  * Select 1 and only 1 configuration file.
  *
  * The "AutoConfig" configuration files will configure the library based on a set of
  * pre-customized configurations for the supported Arduino board type. 
  *
  * These configurations match the the panel configurations and wiring diagrams
  * in the library documentation based on the type of board selected in the Arduino IDE
  * and are compatible with wiring used in earlier versions of the ks0108 library
  *
  * NOTE: if you have a panel that has different dimensions than the distributed configuration, you can either
  * edit the supplied configuration file for that board type or create a fully custom configuration file.
  *
  * The auto configuration file (default is named  "config/ks0108_Panel.h") selects the appropriate board
  * pin configuration file based on the current board selection in the Arduino IDE.
  *   
  * The auto configuration panel configuration files can be found in the "config" directory, the naming is:
  *  "{PANELNAME}_Panel.h"
  * Where:
  *   {PANELNAME} is the glcd panel type. (for example, ks0108)
  *
  * The pin configuration files for each board type can also be found in the "config" directory, the naming is:
  *  "{PANELNAME}_{BOARDNAME}.h"
  * Where:
  *   {PANELNAME} is the glcd panel type. (for example, ks0108)
  *   {BOARDNAME} is the name of the board (as selected in the Arduino IDE).
  *
  * So for example, the auto configuration file name for a ks0108 panel
  * would be: "ks0108_Panel.h"
  * The ks0108 pin configuration file for a "Arduino" board would be: "ks0108_Arduino.h"
  * and the pin configuration file for a "Mega": "ks0108_Mega.h"
  * 
  */

/***********************************************************************************************************
 *
 * BETA TEST NOTE:
 *  - Does the autoconfig work correctly in your environment with your boards and displays?
 *  - Is the mechanism to make a custom configuration easy to use?
 *  - We want your comments and suggestions for making configuration easer, particularly for novices
 *
 * Additional "autoconfig" files can be created, there is an example for 192x64 panels in this distribution.
 * In the future there will be more for different panel types, like sed1520, ks0713, etc..
 * Not all custom configuration files that may be supplied in the release are included in the alpha distribution
 *
 ***********************************************************************************************************/


 /*
  * autoconfig includes - (comment this out if using manual configurations, see below)
  */
//#include "config/ks0108_Panel.h"          // automatically configure library for a ks0108 panel
//#include "config/ks0108-192x64_Panel.h"   // automatically configure library for a ks0108 192x64 panel
#include "config/ks0108-128X128_Panel.h"          // automatically configure library for a 128X128 panel

I didn't have too much time to debug but GLCDDiags didn't compil showing non compatible chip numbers...
Is the process to be followed the same as for a 256X64 configuration?

Thank you again for the great library and for the time you spent supporting.
Raoul

Yes there is a library problem. Looks like you uncovered an old bug.
It looks like somehow a fix a I did LONG ago was lost in the official panel configuration files.
(It was in my private config files I use for my own testing)
I will correct this in the library so that it is fixed in the next update.

Please replace your define for glcd_CHIP_COUNT in your panel configuration file
with this and it should correct the problem.

#define glcd_CHIP_COUNT (((DISPLAY_WIDTH + CHIP_WIDTH - 1)  / CHIP_WIDTH) * ((DISPLAY_HEIGHT + CHIP_HEIGHT -1) / CHIP_HEIGHT))

This happened because we normally don't test vertically stacked chips because
none of the real panels we can test with are made that way, and when I test the
dual display configuration which does use vertically stacked chips, I use a custom
config file that is not part of the normal library.
I found the bug probably a year ago and I thought I put the correction
in all the configuration files, but it seems to now be missing.

Sorry about this.
But thank you for helping make the library better by discovering this issue.

--- bill