
AVR32 NGW100 Driving an STN LCD Module
I’ve had a few controllerless QVGA (320×240) mono LCD modules lying around for a while looking for some use. These are fairly easy to get going with a low-end microcontroller using an external controller IC like the SED1335, but that’s another story. I’d been thinking about doing some sort of integrated home automation project, and since this would need a user interface and I happened to have an NGW100 going spare, getting one of these displays to run on the AP7000’s integrated LCD controller seemed like a nice idea.
The NGW100 only has a 16-bit interface to its already relatively slow DRAM, so driving a high-res colour LCD from it leads to a fairly obvious slowdown. For this application a mono display would be adequate, and easier to drive, requiring only a 4-bit data bus, the 3 clocks and a GPIO to power up the drivers. The LCDC has no problem driving an STN panel, although I had to deviate from the datasheet in one area to get it to work – more on that later.
The particular panel (a Samsung UG32F05) requires a 5 V logic supply, but also calls for around -20 V for the LCD drive. In the prototype this was generated using a nasty buck-boost converter thrown together from a 555 timer and a MOSFET, but this is not recommended (use a real switch-mode controller)! The 5 V was derived with a linear regulator connected to the NGW100’s 2-pin power header, and the signal lines from the LCDC were connected up directly (D0-D3 straight through, PCLK to XSCL/CL2, HSYNC to LP/CL1 and VSYNC to DIN/FLM). Because powering an STN display without the proper clocks applied can cause damage the module provides a /DISPOFF connection, which was driven from a spare GPIO on the NGW100. Normally this would be connected to the LCDC’s PWR output, but this is shared with the SD card detect input on the NGW, and the application would be using this. The pinout of the module goes like this:
Pin | Name | Function |
1 | FLM | Frame scan start (to LCDC_VSYNC) – P7 pin 29 |
2 | M | Backplane sync signal (not used on this module, but connect to LCDC_MODE) – P7 pin 26 |
3 | CL1 | Data latch clock (to LCDC_HSYNC) – P7 pin 27 |
4 | CL2 | Data shift clock (to LCDC_PCLK) – P7 pin 28 |
5 | /DISPOFF | Display inhibit (to GPIO) – P7 pin 5 |
6 | D0 | Display data input (to LCDC_D[0]) – P7 pin 1 |
7 | D1 | Display data input (to LCDC_D[1]) – P7 pin 2 |
8 | D2 | Display data input (to LCDC_D[2]) – P7 pin 3 |
9 | D3 | Display data input (to LCDC_D[3]) – P7 pin 4 |
10 | Vdd | 5V supply |
11 | Vss | 0V supply |
12 | Vee | LCD supply (typically -20V) |
13 | Vo | Contrast (potential divider between Vee and Vss) |
14 | FG | Frame ground |
To get the display working from Linux (I started from a vanilla 2.6.28.1 kernel) I created a copy of the evklcd10x.c board support module, added it to Kconfig and modified it to suit the parameters of the new LCD. The fb_videomode structure was set up as follows:
- refresh = 75
- xres = 320, yres = 240
- pixclock = KHZ2PICOS(1500)
- left_margin = 1, right_margin = 1
- upper_margin = 0, lower_margin = 0
- hsync_len = 2, vsync_len = 1
- sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT
- vmode = FB_VMODE_NONINTERLACED
This gives a refresh rate of around 75 Hz, although this is mis-reported by fbset. The settings in the fb_monspecs structure are not that critical (it seems). I set the frequency ranges based on the quoted timing data for the display. More important is the atmel_lcdfb_info data, which was set up like this:
- default_bpp =1
- default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN
- default_lcdcon2 = ATMEL_LCDC_DISTYPE_STNMONO | ATMEL_LCDC_SCANMOD_SINGLE | ATMEL_LCDC_IFWIDTH_4 | ATMEL_LCDC_INVVD_INVERTED
- guard_time = 2
- default_monspecs = fb_monspecs_structure
- atmel_lcdfb_power_control = lcd_power_control_function
The power control callback function is called by the driver after the controller has been set up and the timing signals are valid. This is used to control the GPIO pin connected to the /DISPOFF input of the panel. It is trivial, and along with an updated initialisation function it looks like this:
#define LCD_nDISPOFF GPIO_PIN_PE(7)
static void lcd_power_control_function(int on)
{
printk(KERN_INFO “Turning LCD power %s\n”,on ? “on”:”off”);
gpio_set_value(LCD_nDISPOFF,on);
}static int __init lcd_board_init(void)
{
at32_add_device_lcdc(0, &lcd_board_lcdc_data,
fbmem_start, fbmem_size,
/* IO port mask */
ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) |
ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) |
ATMEL_LCDC(PE, MODE) |
ATMEL_LCDC_CONTROL);
at32_select_gpio(LCD_nDISPOFF,AT32_GPIOF_OUTPUT); /* LCD /DISPOFF */
return 0;
}
That should be it. However, it turned out that the AP7000 was generating 1/4 the number of clocks per line that it should have been even considering the 4-bit interface (20 clocks instead of 80). Although I established this fact prior to connecting the module, visually this results in a display of vertical stripes. In the datasheet it states that for STN mono mode, HOZVAL (found in the LCDFRMCFG register) is equal to (number of horizontal pixels / interface width) – 1. The Linux driver calculates HOZVAL based on the display type, but does it by the book and chooses a value of 79 (320/4-1). It was found that going against the datasheet and setting HOZVAL=319 solved the problem. This was implemented by patching atmel_lcdfb.c so that hozval_linesz = info->var.xres (around line 577). Please feel free to point out where I have screwed up here, or if this is indeed a mistake in the databook!
Once the board boots you can use fbset -depth 4 to switch to 16 shade greyscale mode. The photo above shows the Qt text editor demo running in this mode. Certain shades of grey exhibit a slight flicker, but for an STN display the image is pretty reasonable.
Howdy,
I am attempting to use a very similar display. How did you connect to the data lines? Maybe I am reading the schematic wrong, but they appear to be connected up to the eth1 mac and not on the header?
Thanks!
Ah, I see, there is another set of data lines on the PE port.
Well, wish me luck, let’s see if I can duplicate your success 😉
Hi,
Yes, some of the hardware modules are available on more than one set of pins. The required set is selected in lcd_board_init, above. All the required LCDC signals are available on J7 on the NGW100, and I used PE07 (pin 5) for the power on/off output. I will update the text with the specific connections.
I assume you know about: http://www.avrfreaks.net/wiki/index.php/Documentation:NGW/NGW100_Expansion_connectors
Mike
Hi,
I have got the exact same display, but I have been unable to find a datasheet for it.. If you can, please send it to my email, that would be much appreciated 🙂
Thanks!
Hi Johannes,
It’s a long time since I did anything with this display and I’m pretty sure I never found the actual datasheet for it. According to my notes it is near enough identical to an Epson A0635.
Mike
hi
what about the -20V circuit ? could you post the schematic of your solution ?
http://mikestirling.co.uk/files/lcd_buck_boost_555.png
I strongly advise you don’t use this circuit!
The circuit is a basic inverting buck-boost converter. It has no feedback and therefore generates an output voltage which is related to the (5V) input by a fixed ratio given by the duty cycle. The 7555 output does not have enough drive strength to drive the MOSFET properly, so this is in fact only barely functional.
If your circuit has a microcontroller with PWM hardware then you could use that instead of the 555 for improved performance. The formula for calculating the required duty cycle can be found in any text on SMPSU design.