MCU Friend Displays - Move LCD_D Bus to Another Port on Mega 2560
by Gilissen Erno in Circuits > Arduino
37 Views, 0 Favorites, 0 Comments
MCU Friend Displays - Move LCD_D Bus to Another Port on Mega 2560
MCU Friend display with a Parallel LCD Bus have a huge disadvantage: the routing is optimized for use with an UNO. The UNO has several restrictions (32Kbyte Flash, 2Kbyte RAM) what make it virtually impossible to use this controller with the display (unless for very small projects). The display can be 1:1 connected to a Mega but this has 2 disadvantages:
- The Mega uses 3 different IO ports for D2 ... D9, so display experience is far slower vs. the UNO.
- All PWM timer outputs on the Mega are in those LCD bus pins. If you need the timer outputs, you cannot use the Parallel display anymore.
Solution: move the Parallel connected display bus to another set of Mega pins. This allows us to use a speed optimized LCD connection. Roughly estimated, this solution might be more than 10 times faster on the same Mega controller (compared to the original MCU Friend connection and library). Simply because hardware data in/out is the same as how the software expects the data (so no shifting and masking over multiple ports). The Arduino Mega is a 8bit 16MHz architecture: we cannot increase its speed. So the only way to improve display performance is to optimize the hardware to avoid the software has to perform too much tasks to write to the display.
Some info about this display is also on the arduino forum.
The major disadvantage of this change is you have to modify the library. Worst case: every time you connect the LCD_Dx pins to another port for a different project, you have to modify the library accordingly (or make additional options available for each possible port connection). Every library update is expected to roll back your local changes.
Supplies
- MCU Friend Parallel Display
- Arduino Mega 2560.
Note:
- The MCU Friend Arduino library screenshot shows the inefficiency of Arduino Mega connections compared to Uno connections. This is the result some functionality on the ATMega328 (Arduino UNO) is shifted to other ports on the ATMega2560 (Arduino MEGA2560). From software perspective, the UNO vs. MEGA compatibility on D8 ... D13 is most likely quite OK, but it makes the pins unsuitable as LCD_D? pins since the data is mixed over too many hardware resources.
Hardware Compared
This image shows the Uno and Mega compared. The red marked area shows the MCU Friend Parallel Display connections. Pins not used the the display are A5, D0 (RxD) and D1 (TxD). If the SD card is not used, D10 up to D13 are also free.
As a proof of concept, we want to move Arduino D2 ... D9 to Arduino A8 ... A15 (further I explain why this group of pins is recommended). So Arduino A8 gets connected to the display LCD_D0, Arduino A9 connects to LCD_D1 up to Arduino A15 being connected to LCD_D7.
My change request to MCU Friend library developers would be:
- Make it more flexible to use other pins or complete IO ports.
- The function reading touch can leave XM and YM as analog inputs, but when writing to the display these pins must be changed to digital outputs without the user having to do that.
I'm not using Arduino that often, so if anybody has a tip to make this solution more clean, please let me know!
LCD Bus Compared
The table shows how Arduino pins D0....D9 and A0...A4 are used to connect to the MCU Friend parallel display.
Clearly visible:
- UNO connection requires two I/O ports, no bit positions are shifted. So LCD_D0 is connected to the 0th bit of the I/O Port. This goes up to LCD_D7, being connected to the 7th bit of the same I/O Port. That way, there is no need the software has to shift or distribute data over multiple I/O ports.
- Mega has the same connection in terms of position. But that connector is routed to an additional I/O port. Besides that, the bit positions are shifted. As a result, the AVR core has to start shifting data on top of the bit masking, making the display access on Mega considerable slower.
Some searches claim the F_CS pin is related to the touch interface, but a brief examination of the driver source code did not give any indication this pin is actively used (for this reason I consider Arduino A5 unused by the MCU Friend display).
MCU Friend Library Changes
Locate the directory MCUFRIEND_kbv in your Arduino Library directory.There you find a directory utility. In there is a file mcufriend_shield.h. Open this file using a text editor (ex. NotePad++).
If you use a touch version of the display, you cannot move A1 and A2. Those pins are used by the touch interface (I come back to that later). All other pins can be moved. For performance reasons, make sure to connect LCD_Dx to any IO port that is completely available, preserving the number (what I mean is: you connect LCD_D0 to PORTK0, LCD_D1 to PORTK1 and so on). In my case, I didn't need the Analog pins for my project, so I used Arduino A8 ... A15 that correlate to PORTK (bit 0 to bit7). As I don't mix ports nor swap bits in the port, the #define macro becomes straightforward: write_8(x) = PORTK=(x) and so on.
Notes
- I experienced the display update was sometimes a mix of previous and present data. Since we have no datasheet from the display controller (according to available data, an RM68140), I have no idea about the timing. Therefore I added the write8(x) to be two times write_8(x). This slows down the AVR core by a few clocks on every display data exchange.
- In order to ensure the compiler takes the correct macro expansion, you have to un-comment the first statement in the library: #define USE_SPECIAL. Otherwise the Compiler will just compile the library for the Mega.
This is the lib change as text, so you don't have to re-type. My changes are in bold and may be changed to another port (see further).
#if defined(USE_SPECIAL)
//#include "mcufriend_special.h"
#warning WE ARE USING A SPECIAL CUSTOM DRIVER
#define RD_PORT PORTF
#define RD_PIN 0
#define WR_PORT PORTF
#define WR_PIN 1
#define CD_PORT PORTF
#define CD_PIN 2
#define CS_PORT PORTF
#define CS_PIN 3
#define RESET_PORT PORTF
#define RESET_PIN 4
#define write_8(x) PORTK = (x)
#define read_8() PINK
#define setWriteDir() DDRK = 0xFF
#define setReadDir() DDRK = 0x00
#define write8(x) { write_8(x); write_8(x); WR_STROBE; }
#define write16(x) { uint8_t h = (x)>>8, l = x; write8(h); write8(l); }
#define READ_8(dst) { RD_STROBE; dst = read_8(); RD_IDLE; }
#define READ_16(dst) { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }
#define PIN_LOW(p, b) (p) &= ~(1<<(b))
#define PIN_HIGH(p, b) (p) |= (1<<(b))
#define PIN_OUTPUT(p, b) *(&p-1) |= (1<<(b))
#if !defined (USE_SPECIAL_FAIL)
#warning WE ARE USING A SPECIAL CUSTOM DRIVER
#endif
#endif
Touch Interface
The resistive touch interface requires some attention: this has two X connections (XP and XM) and two Y connections (YP and YM). To determine the Y position, XP is made HIGH, XM made LOW and the controller measures the ADC voltage on YM. Similar, to determine the X position, YP is made HIGH, YM is made LOW and the ADC voltage on YM reflects the X position. For this reason, XM and YM are analog capable inputs. MCU Friend designers shared the display bus LCD_7 and LCD_6 with XP and YP connections. If you move the bus, the touch hardware moves accordingly. In my case, when I move to PORTK (A8...A15), the following touch interface change must be made:
MCU Friend based #defines: New #defines:
#define XP (6) #define XP (A14)
#define XM (A2) #define XM (A2)
#define YP (A1) #define YP (A1)
#define YM (7) #define YM (A15)
Note other complete ports available to the Arduino Mega are PORTA, PORTC and PORTL. For convenience, I list below the Arduino Digital number as Name. The touch interface access changes according to the port used by LCD_D0 ... LCD_D7.
Alternative Mega Ports
The table shows what other complete ports are available on Arduino Mega: PORTA, PORTC, PORTK and PORTL. Using a complete port with each bit directly connected does not require software intervention to put it at the correct spot. The only disadvantage of a complete port is that you also use the functionality. For that reason, I didn't list PORTE, since it contains the UARTs and usually at least one is required for debugging / PC connection. The yellow marked pins are the alternative digital IO pins for the touch interace (see step 4).