Code Repo    |     RSS
MD's Technical Sharing



Tuesday, March 11, 2014

Using picojpeg library on a PIC with ILI9341 320x240 LCD module

I purchased a 320x240 LCD module which supports 320x240 resolution and comes with an SD card slot from eBay:


This LCD is using the ILI9341 controller supporting SPI mode. Within minutes I was able to sketch a program which draws text and graphics on this LCD without difficulty based on the sample code provided by adafruit:


Since the LCD resolution is high, I decided to attempt something which I have never done before, and which many hobbyists consider a great challenge on this 16-bit micrcontroller: decoding and displaying JPEG images from the SD card.

Finding a JPEG decoder library

The first candidate that came to my mind was the Microchip Graphics Library, specifically built for 16-bit and 32-bit PICs, as I have good experience with their Memory Disk Drive library, which is very robust and capable of handling various file systems. However, a quick look at the files after download revealed that things are not so simple - the library sample application is made to work with various PIC families and is designed to read graphics images from certain flash memory chips and display them onto a few supported LCD displays. As my ILI9341 is not supported, I figured that it would be a challenge to clean up the code just to get the part that I wanted, and decided to find a cleaner JPEG decoder library.

With some research, I chose picojpeg, an open source JPEG decompressor written in C in a single source file with specific features optimized for small 8/16-bit embedded devices. After getting the sample application (which converts JPEG to TGA files) working using Visual Studio, I proceeded to port the library to C30.

Porting picojpeg to C30

The library consists of just 2 files, picojpeg.c and picojpeg.h which use standard ANSI C and should compile under C30 with no issues. However, the sample application, jpg2tga.c which contains example code to use the library to decode JPEG, is written with Windows and Visual Studio in mind and will need adjustment to work under C30. Specifically, declarations with int, long and similar data types will need to be modified as int on Windows defaults to 32-bit whereas it is 16-bit in C30. Also, since right shifts under C30 are always unsigned, the following preprocessor will need to be declared and set to 1, as commented in picojpeg.c, otherwise the colors displayed will be wrong:

// Set to 1 if right shifts on signed ints are always unsigned (logical) shifts
// When 1, arithmetic right shifts will be emulated by using a logical shift
// with special case code to ensure the sign bit is replicated.
#define PJPG_RIGHT_SHIFT_IS_ALWAYS_UNSIGNED 1


By adapting the code from the jpg2tga sample application, I wrote a helper file, jpeg_helper.c, with the following function to read a JPEG file from the SD card and draw on the LCD.

JPEG_Info pjpeg_load_from_file(const char *pFilename, int reduce, unsigned char showHorizontal)

Pass 1 to showHorizontal to display the image in landscape mode on the screen. Pass 0 to display it in portrait mode.

As image data in a JPEG file is internally stored as a number of relatively small independently encoded rectangular blocks, usually 8x8 or 16x16, called Minimum Coded Units (MCU), one does not have to read the entire JPEG file into memory before displaying it. Therefore, even with the limited memory of a PIC, it is possible to display big JPEG files (subject to file system size limitation and LCD resolution) on the LCD by reading data and decoding them as the image is being rendered. This also makes it possible to load a scaled-down version of a high resolution JPEG file by simply rendering the first pixel of each MCU block, instead of the whole block. To display a scaled-down version of the image, pass 1 to the reduce parameter.

For simplicity, the jpeg_load_from_file function does not handle grayscale JPEG files.

With the above changes, I managed to use the picojpeg library to display a 320x240 JPEG on the LCD. At 32 MHz clock speed on a PIC24HJ128GP202, it took 10 seconds for the PIC to finish reading the image data from the SD card, decoding the image and display on the LCD. The process is shown in the following video.



The original photo can be downloaded here.

In my test, by plotting only the first pixel of each MCU, on the same PIC configuration, a 2816x2112 (2.41MB) JPEG file finished rendering on the 320x240 LCD in 105 seconds with no issues.

Overclocking the PIC

Although it is amazing to me that a 16-bit micro controller at 32 MHz is able to render big JPEG files, the speed (10 seconds for a 320x240 image and 105 seconds for a scaled-down display of a 2.41MB image) is too slow for any practical purposes. For a faster rendering speed, I decided to operate the PIC at a faster clock speed. Still using the internal oscillator, this is done by increasing the frequency multiplier:

// Using internal oscillator = 7.37MHz
// Running Frequency = Fosc = 7.37 * PLLDIV / 1 / 2 / 2 
// Output at RA3 = Fosc / 2 
CLKDIVbits.FRCDIV = 0;      // FRC divide by 1
CLKDIVbits.PLLPOST = 0;     // PLL divide by 2
CLKDIVbits.PLLPRE = 0;      // PLL divide by 2
PLLFBDbits.PLLDIV = 15;     // Freq. Multiplier (default is 50)

According to the datasheet, the PIC24HJ128GP202 can run at a maximum of 80MHz @ 40 MIPS, by setting the multiplier to approximately 43. During my experiment, the PIC still seems to run at 100MHz and is able to do simple UART communications, although the device would get slightly hot. Above 100MHz and up to 120MHz issues start to arise, for example, program would terminate unexpectedly with MPLAB reporting "Target Halted.". By opening View > File Registers and examining the RCON register at address 0740, it looks like a brown-out reset has occured (bit 1 of RCON is set, sometimes bit 0 is set as well). On the PIC24HJ128GP202, there is no way to turn off the brown out reset feature - it is unconfigurable. Above 120MHz, MPLAB would not even successfully start debugging the program on the PIC using PICKit2.

PIC clock speed vs. SD card SPI speed

At high clock speed and with the internal oscillator, there will also be problems of selecting the correct BRG value for the UART baud rate - in fact when testing at 100MHz, I could only get UART to run at 9600bps! As UART is mostly used for debugging in my case, this should not be an issue. Another greater issue is with the SD card SPI clock speed as many older SD cards support up to 20MHz only but the MDD library by default runs the SD card SPI clock at 1/4 of of the PIC clock speed. This is seen in the SYNC_MODE_FAST declaration in SD-SPI.h:

// Description: This macro is used to initialize a 16-bit PIC SPI module
#ifndef SYNC_MODE_FAST
    // primary precaler: 1:1 secondary prescaler: 4:1
    #define   SYNC_MODE_FAST    0x3E
#endif

This means that even at just 80MHz PIC speed, the SD card SPI speed would be at 20MHz - reaching the maximum supported speed of some cards. To work around this, the SPI pre-scalers would need to be changed to 8:1 to reduce the speed to just 10MHz:

#define   SYNC_MODE_FAST    0b111010

This reduces the SPI speed by half, making reading of SD card data and rendering of the image slower, defeating the purposes of overclocking.

In my tests, even at just 64MHz, intensive reading of JPEG data from the SD card would fail randomly and unexpectedly if the circuit is built on a breadboard. Migrating to a strip board fixes the issue and allows the clock speed to be increased. I attributed it to stray capacitance on the breadboard which becomes a problem as the SD card SPI frequency increases. In fact, 32 MHz is the maximum speed at which I could get the circuit running reliably on a breadboard.

The MPLAB source code of the ported picojpeg library can be downloaded here.
Read More »

Thursday, January 9, 2014

Interfacing HY28A LCD module with ILI9320 controller and XPT2046 resistive touch panel to PIC microcontroller

This is a cheap 320x240 2.8" TFT LCD module that uses the ILI9320 controller for the display and the XPT2046 controller for the resistive touch panel. I purchased the module over a year ago but only had the opportunity to try it out recently. The module has since been phased out by the manufacturer and replaced with the HY28B that uses the ILI9325C controller.

Physical connections

The module has two 20-pin connectors on each side:

To my disappointment, the connectors on this module use 2mm pitch, and not the standard 2.54mm (0.1") pitch used by most hobbyist breadboards, sockets and connectors. I also tried to search eBay and could not find anything that might be useful, other than a few 6-pin connectors for the Zigbee module which also happens to use 2mm pitch, although I did find a photo here taken by someone who has jumper cables with small headers fitting the 2mm pin pitch of this module.

This is the time when some creativity is needed. Luckily since many of the parallel communication pins on the two 20-pin connectors on both sides of the module are not used in SPI mode, I am able to break some of the unused pins, leaving space for me to bend other pins and solder them to standard 2.54mm male connectors in order to fit a breadboard:


Interfacing the LCD module

Although the ILI9320 supports both parallel and serial communications, the HY28A module is configured to only use SPI. Using the example source code provided by the seller, I was quickly able to make this LCD show some text and graphics:


One interesting thing to note about the ILI9320 is that it uses SPI mode 3, not SPI mode 0 like many other SPI devices. This Wikipedia article has a good description on the different clock polarities and phases used by each SPI mode. From a PIC point of view, this means setting the correct value for bit 8 (CKE - Clock Edge) and bit 6 (CKP - Clock Polarity) in the SPI1CON1/SPI2CON1 register according to the datasheet:

bit 8 CKE: SPIx Clock Edge Select bit
1= Serial output data changes on transition from active clock state to idle clock state (see bit 6)
0= Serial output data changes on transition from Idle clock state to active clock state (see bit 6)

bit 6 CKP:Clock Polarity Select bit
1= Idle state for clock is a high level; active state is a low level
0= Idle state for clock is a low level; active state is a high level

For mode 0 (most SPI devices), you will need to set CKP = 0 and CKE = 1. For mode 3 (the ILI9320), CKP = 1 and CKE = 0.

Interfacing the touch screen

There are two variants of the HY28A module, one with the ADS7843 controller for the resistive touch screen and the other with the XPT2046 touch controller. The main difference is that the ADS7843 outputs analog voltages while the XPT2046 uses an SPI interface for the touch controller. My module uses the XPT2406 and has 5 pins:

TP_IRQ - Interrupt Request. Low when a press is detected.
TP_CS - SPI Chip Select
TP_SDO - SPI Data Input
TP_SDI - SPI Data Output
TP_SCK - SPI Clock

Like most other resistive touch controllers, the XPT2046 will return a raw coordinate value when a press is detected on the panel. For the coordinate to be useful, the code must convert it to a coordinate within the LCD resolution. To make things simple, the code can just look at the maximum and the minimum values that are returned when a press is detected on each corner of the panel and perform a linear conversion of the values to LCD coordinates:

// height and width of LCD 
#define MAX_X  240UL
#define MAX_Y  320UL  

// coordinates of sample touch points at 4 corners of touch panel
#define TOUCH_X0 255 
#define TOUCH_Y0 200 
#define TOUCH_X1 3968
#define TOUCH_Y1 3775

// calibration constants
cal_x = (TOUCH_X1 - TOUCH_X0) / MAX_X;
cal_y = (TOUCH_Y1 - TOUCH_Y0) / MAX_Y;
    
// get the raw touch coordinates
xpt2046GetAverageCoordinates(&tX, &tY, 5);

// convert to LCD coordinates
pX = (tX - TOUCH_X0) / cal_x;
pY = (tY - TOUCH_Y0) / cal_y;

Reading of the touch points can be done when TP_IRQ is low, indicating that a touch is detected. To reduce noises and achieve better accuracy, it will be better to perform several reads (5~10) for every press and calculate the average coordinate of the touched points. TP_CS must remain low when reading is performed, and set to high when reading is done. Coordinates reading must be stopped as soon as TP_IRQ is high, indicating that touch presses are no longer detected.

I was quickly able to prototype a program that allows me to draw on this resistive touch panel:


If you can't see it, the text reads "PPDS STMJ" and "BAHX MBA". The isolated drawing points are from the noises due to breadboard stray capacitance. A median filter can probably be used to remove these isolated points for better accuracy.

I also tried to connect the drawn points and achieved a better output:




The text reads "Hello ABC" in the first picture and "123" in the second picture. Ignoring the inappropriate connections between two adjacent characters (due to the inability to detect when the stylus is released from the screen to stop connecting points), the other problem is the zig-zag and not smooth shape of the drawing. This is probably because of the slow speed of the PIC24. At 16MHz SPI speed and 32MHz clock speed on my PIC24FJ64GA002, some precious time is wasted communicating with the touch controller, calculating the touched coordinates and plotting them. During this time, other points drawn by the user were lost and not plotted on the screen.

As it takes considerable time to read the touch points and plot them, it is not possible to migrate the entire process into an interrupt to increase touch sensitivity as an interrupt routine also needs to finish executing as fast as possible. The only solution for a smooth drawing would be a much faster clock speed, or perhaps to use Direct Memory Accessing (DMA), supported by this PIC. However, at this moment I do not yet have the time to explore either option.

Sample code download

C30 code for the ILI9320
C30 code for the XPT2046

Codes for both the LCD and the touch panel make use of my custom SPI library for the PIC24FJ64GA002 to facilitate SPI communication. Before working with the LCD or the touch screen, you will need to initialize the SPI modules using the spiInit method from my SPI library as shown below:

spiInit(1, 0b00011011, 0); // SPI Module 1 for Touch Screen, secondary prescale 2:1, primary prescale 1:1, SPI mode 0
spiInit(2, 0b00011011, 3); // SPI Module 2 for LCD, secondary prescale 2:1, primary prescale 1:1, SPI mode 3

Assuming that the PIC is running at 32MHz, the above code will set the SPI clock at 16MHz, fast enough for many purposes.
Read More »

Friday, November 15, 2013

Experimenting with ST7735 1.8-inch 128x160 color LCD on a PIC microcontroller

This tiny 1.8-inch LCD module is the second color LCD that I successfully attempted (the first is the Nokia 3510i LCD). The breakout board which I purchased from eBay also comes with an SD card socket:


 
The pinout for the board is as follows, inclusive of the SD card connections: 

1.  GND
2.  VCC 
3.  NC
4.  NC
5.  NC
6.  LCD RESET
7.  LCD A0 (R/S)
8.  LCD SDA
9.  LCD SCK
10. LCD CS
11. SD SCK
12. SD MISO
13. SD MOSI
14. SD CS
15. LED+
16. LED-


Interface via SPI

This LCD controller, ST7735, uses SPI for communication and requires just 5 data lines, namely RESET, A0, SDA, SCK and CS. Of particular note is the A0 line, also known as R/S, which indicates whether the bytes being transferred should be interpreted as command or as pixel data. Although SPI communication should preferably be done using the hardware SPI module (there are two on my PIC24FJ64GA002) for faster display speed, it can also be done via bit-banging if hardware SPI is not available. The following function will send a byte via SPI using software:

void write_spi_byte(unsigned char c){
    char x;
    for(x=0;x<8;x++){       
        LCD_SCK = 0;
        LCD_SDA = 0;
        if(c & 0x80)
        LCD_SDA = 1;
        LCD_SCK = 1;
        c <<= 1;
    }
}

I converted the Adafruit's Arduino library for this LCD to compile under Microchip C30 compiler for my PIC24FJ64GA002 and the LCD is able to draw some graphics nicely: 

Using the bundled SD card socket and Microchip MDD library, together with my custom 5x7 font, I was able to display some SD card information on the LCD: 

 

The board I purchased has an AMS1117 on-board regulator and expects at least 5V to be supplied to VCC to be able to generate 3.3V for the LCD and SD card to work. I did not know this and supplied 3.3V to VCC initially, only to find out that the SD card worked intermittently while the LCD still worked well. If you have problems with the SD card on this module, check if this is the case. 


Setting the color model

The ST7735 controller supports up to 262,144 (218) colors. However, to be able to use 262K colors, for each pixel, 18-bit of data have to be transferred via SPI. Since this increases the complexity. I have decided to stay with 65,536 colors (16-bit) colors, where pixel data can be transferred nicely just by using 2 SPI writes.  

In 16-bit color mode, the LCD expects pixel data to be in RGB565 format. The following will convert from the well-known RGB888 (24-bit color) format to RGB565: 

#define RGB565(r,g,b) ((((r>>3)<<11) | ((g>>2)<<5) | (b>>3)))   

An interesting point to note about this LCD is that there seems to be two variants with slightly different behaviors. If your module comes with a black tab, the BLUE and RED byte of each pixel will be swapped, resulting in the wrong color being displayed. If your module has a red or green tab, the byte order for each pixel will be correct.  

To fix this issue, you can change the above RGB565 macro to swap the red and blue byte, or you can change the value of the MADCTL register during initialization: 

writecommand(ST7735_MADCTL);

// R and B byte are swapped
// writedata(0xC8);

// normal R G B order
writedata(0xC0);


Downloads

Various bitmaps from my SD card as shown on the LCD:


The C30 source code for this LCD can be downloaded here.
Read More »

Sunday, November 3, 2013

Experimenting with ST7920 128x64 graphical LCD on a PIC

This is a monochrome 128x64 graphical LCD using the ST7920 controller that I purchased from eBay:


The module is using a 20-pin standard 2.54mm connector, making it easy for prototype development on a breadboard:


Communication modes

According to the datasheet, the following communication modes are supported:
  • 8-bit mode. Data or instruction bytes are transferred via pin DB7-DB0.
  • 4-bit mode. Data or instruction bytes are separated into two parts. Higher 4 bits will be transferred through DB7-DB4, followed by the lower 4 bits. The DB3-DB0 pins will not be used and should be connected to ground. 
  • Serial mode. This is done by pulling down the PSB pin. When enabled, communication will only require 4 pins in total. Only writing data is supported in serial mode
Unfortunately, the board that I purchased has the PSB pin permanently connected to VCC. Hence, only parallel communication is possible. To cut down on the number of output pins required, I have selected 4-bit mode, instead of 8-bit.

The LCD supports both graphics and text modes:
  • Maximum 16 characters x 4 lines in text mode
  • 128x64 resolution in graphics mode.

Initialization codes

The following code performs LCD initialization and configures 4-bit communication in text mode:

void LCD_Init(void) 
{ 
 LCD_REST=1; 
 LCD_REST=0; 
 delay_ms(5);
 LCD_REST=1;  

 delay_ms(50);

 LCD_WriteCommand(0b00100000); 
 delay_ms(5);

 LCD_WriteCommand(0b00100000); 
 delay_ms(5);
 
 LCD_WriteCommand(0b00001100); 
 delay_ms(5);

 LCD_WriteCommand(0x01);
 delay_ms(5);

 LCD_WriteCommand(0x06);
 delay_ms(5);

 LCD_WriteCommand(0b00000010);
 delay_ms(5);
}

After the LCD has been initialized, the following function will display a string on the LCD:

void LCD_TextDisplayString(unsigned char line, char* string)
{  
    unsigned char addr,i; 
    if(line==1) 
        addr=0x80; //The first line address
    else if(line==2) 
        addr=0x90; //The second line address
    else if(line==3) 
        addr=0x88;   //The third line address
    else if(line==4) 
        addr=0x98;    //The fourth line address 

    LCD_WriteCommand(addr); 

    for(i=0;i<16;i++) 
        LCD_WriteData(*string++); 
} 
This is how it will look when displaying 4 lines of text:

Displaying graphics

Despite the large screen resolution, the default text mode only allows me to display up to 64 characters on the screen due to the thick font. My next attempt is to use graphics mode, so that I can use my custom font and display more characters. The following code shows how to enable and disable the graphics mode on this LCD:
void LCD_EnableGraphics(void)
{
 LCD_WriteCommand(0x20);  
 delay_ms(1);
 LCD_WriteCommand(0x24); 
 delay_ms(1);
 LCD_WriteCommand(0x26);
 delay_ms(1);
}

void LCD_DisableGraphics(void)
{
 LCD_WriteCommand(0x20);
 delay_ms(1);
}

Similar to the Nokia 5110 LCD, every 8 pixels on this LCD will consume a single byte in the display memory space. With that knowledge I was quickly able to use my custom 5x7 bitmap font and display more characters. The following picture is the display showing information from various sensors that I have interfaced with the PIC24FJ64GA002. It can show up to 16x8=128 characters:
Various graphics that I manage to display on this LCD:
The full C30 source code for this LCD can be downloaded here. If you are interested, the syntax highlighting of the source code in this article is done using this tool.
Read More »

Wednesday, March 23, 2011

Interfacing Nokia 3510i and 5110 LCD with PIC Microcontroller

Recently I started to regain some interest in embedded systems, and start to experiment with PIC micro-controllers. After some successful attempts with standard character LCDs using using the HD44780 controllers, I decided to get some Nokia LCD modules from eBay to explore.

The 2 LCD modules I purchased are for the 3510i and 5110 models. Both have built-in controllers which use Serial Peripheral Interface (SPI). The following are the pinout for my modules, notice that pin assignments may vary slightly.

LCD pinout

Nokia 5110:



Nokia 3510i:

The only different here is pin #5 which is used as data/command selection for the 5110, and unused for the 3510i.

Voltage difference: 5.5v vs 3V

Both LCDs are designed to work with 3.3V, but due to an internal voltage clamp 5V can be used for SCLK, SDATA, REST, D/C and CS as long as a current limiting resistor (around 10k) is connected in series for each line. 3.3V should still be applied to VCC and the LED supply. I have tried using voltage dividers, which did not work, perhaps due to the LCD varying internal resistance and current consumption.

With the above connections we can only write to the LCD but can't read back the LCD response because 3.3v is not high enough to register as logic '1' in the PIC. Luckily reading from the LCD is not required for basic operations; all that is needed is sufficient delay after each operation to make sure the LCD is ready for next command.

I have chosen the PIC16f88 simply because it's available in my junk box. For simplicity, I have decided to use bit-banging to send data, and not the PIC built-in SPI module. Although this usually means complicated code and lower throughput, it does not matter as all I wanted is to get the LCD to display something useful ;)

LCD Memory Map

The 5110 LCD is monochrome, uses the PCD8544 controller and has a resolution of 48 rows × 84 columns. Each 8 pixels on a single column consumes a single byte on the LCD memory map. It takes 504 bytes to fill the entire LCD.

The 3510i LCD has 97x66 resolution and can operate in either 256 or 4096 colors. Since there seems to be little difference between 256 and 4096 colors due to the small resolution, I have chosen 256 colors for simplicity. Each pixel on the LCD is represented by a single byte and filling the entire LCD takes 6402 bytes in 256-color (8-bit) mode.

Sample code: displaying test patterns

The following code shows how to display all black pixels on the Nokia 5110 LCD. Notice that LCD initialization code is not shown.

void lcd_5110_clear()
{
    for (int i=0; i<84;i++)
    {
        unsigned char row;
        for (row=0;row<6;row++)
        {
            //all black pixels
            char data = 0xFF;
            
            lcd_5110_send(0x40 + row,0); //Y address
            lcd_5110_send(0x80 + i,0);   //X address
            
            //write to display memory
            lcd_5110_send(data,1);
        }
    }
} 


The following code shows how to display a selected color on the 3510i LCD:

void addset(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2)
{
    send(0x2a,0);//column address set
    send(x1, 1);
    send(x2, 1);
    send(0x2B, 0);//page address set
    send(y1, 1);
    send(y2, 1);
    send(0x2C,0 );//memory write
}
void LCD_Clear(unsigned int value,unsigned char Color)
{
    unsigned char x, y;
    addset(0,0,97,66);
    for(y = 0; y < 67; y ++)
    {
        for(x = 0; x < 98; x ++)
        {
            send(Color, 1);
        }
    }
} 


Displaying text and graphics

Up until now you can only display test patterns on the LCDs. The use of a bitmap font (and extra code) is required if you want to display any useful text. I have chosen a 8x12 font for the 3510i LCD, and a 5x8 font for the 5110 LCD. The font, together with any graphics to be displayed, will be stored in a 24C64 (8Kbytes) I2C EEPROM. To program the EEPROM, I use the I2C version of the PonnyProg programmer. Notice that this may not work on newer PCs where the available current from the serial port is limited and will never work with a USB-to-serial converter. In my experiment, I made a stupid mistake of adding a LED via a 470 ohm resistor to show activity during programming. This result in data corruption and verification errors after programming due to excessive current consumption. Changing the resistor to 2k worked fine, although the LED is much dimmer.

With the EEPROM to store font and graphics, the 5110 LCD could now display text and some monochrome bitmap:


The 3510i LCD could do a much better job ;)


Notice that the serial port connector is for debugging purposes only.

The entire source code is attached here. The contents of the EEPROM is included with the source code and named eeprom.bin.

See also:

ST7735 1.8" 128x160 color LCD
ST7920 128x64 graphical LCD
Other LCD modules that I have interfaced
Read More »

Wednesday, February 9, 2011

Experimenting with LCD modules and PIC microcontrollers

I recently got a PIC16LF84A (free sample from Microchip) and a few LCD modules at a cheap price from eBay. With some interests and time at hand, I have successfully made these LCD modules work and display some test patterns, just for fun :)

16x2 Character LCD

This LCD is using the standard HD44780 controller so sample source code can be found everywhere on the Internet. I got it to work within 15 minutes:



20x4 Character LCD

This LCD is also using the standard HD44780 controller, but there is more display area, 20 columns and 4 lines. I also got it to work:


Download the source code to test the 16x2 and 20x4 character LCD here.

122x32 Monochrome Graphics LCD

This LCD is using the JHD12232D controller. I purchased it from sure-electronics, an eBay reseller:


Despite being a graphical LCD, its uses are pretty limited due to the small vertical resolution. The 32-pixel vertical resolution is divided into 2 blocks of 16 pixels each, having a space in between. This make it almost impractical to display any bitmaps or graphics on this LCD. The only graphical use for this LCD would be to display Chinese text, as demonstrated in the above picture.

Using the datasheet and sample source code available from the seller website, I am able to make this LCD display some test patterns:


Download the datasheet and source code here
Read More »