PIC8 Trainer - Module LCD - FORDATA FDCC2004B ST7066U (HD44780 Compatible) - 4x20.

0.Contents

PIC18F Trainer : PIC18F2620 @8MHz Internal oscillator.

1.String & Custom Patterns - 8-Bit No Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 8-Bit No Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD.
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> GND.
// MODULE.06 -> MCU.RA1.
// MODULE.07 -> MCU.RB0.
// MODULE.08 -> MCU.RB1.
// MODULE.09 -> MCU.RB2.
// MODULE.10 -> MCU.RB3.
// MODULE.11 -> MCU.RB4.
// MODULE.12 -> MCU.RB5.
// MODULE.13 -> MCU.RB6.
// MODULE.14 -> MCU.RB7.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_E										LATAbits.LATA1
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_E_TRIS									TRISAbits.TRISA1
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_displayClear(void);
void st7066u_initialize(void);
void st7066u_writeData(char cData);
void st7066u_writeInstruction(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom patterns";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;

	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x02);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_displayClear(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_writeData(char cData)
{
	ST7066U_RS = 1;
	ST7066U_E = 1;
	ST7066U_DATA = cData;
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeInstruction(char cData)
{
	ST7066U_RS = 0;
	ST7066U_E = 1;
	ST7066U_DATA = cData;
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

2.String & Custom Patterns - 8-Bit With Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 8-Bit With Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD.
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> MCU.RA1.
// MODULE.06 -> MCU.RA2.
// MODULE.07 -> MCU.RB0.
// MODULE.08 -> MCU.RB1.
// MODULE.09 -> MCU.RB2.
// MODULE.10 -> MCU.RB3.
// MODULE.11 -> MCU.RB4.
// MODULE.12 -> MCU.RB5.
// MODULE.13 -> MCU.RB6.
// MODULE.14 -> MCU.RB7.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_DATA_BF									PORTBbits.RB7
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_RW										LATAbits.LATA1
#define ST7066U_E										LATAbits.LATA2
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_RW_TRIS									TRISAbits.TRISA1
#define ST7066U_E_TRIS									TRISAbits.TRISA2
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_displayClear(void);
void st7066u_initialize(void);
void st7066u_readBusyFlag(void);
void st7066u_writeData(char cData);
void st7066u_writeInstruction(char cData);
void st7066u_writeInstructionNBF(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom patterns";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_RW_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;

	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x02);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_displayClear(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_readBusyFlag(void)
{
	ST7066U_RS = 0;
	ST7066U_RW = 1;
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0xff;
	do{
		ST7066U_E = 0;
		ST7066U_E = 1;
	}while(ST7066U_DATA_BF);
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;
}

void st7066u_writeData(char cData)
{
	st7066u_readBusyFlag();
	ST7066U_RS = 1;
	ST7066U_RW = 0;
	ST7066U_E = 1;
	ST7066U_DATA = cData;
	ST7066U_E = 0;
}

void st7066u_writeInstruction(char cData)
{
	st7066u_readBusyFlag();
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_E = 1;
	ST7066U_DATA = cData;
	ST7066U_E = 0;
}

void st7066u_writeInstructionNBF(char cData)
{
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_E = 1;
	ST7066U_DATA = cData;
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
	st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

3.String & Custom Patterns - 4-Bit Low Nibble No Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 4-Bit Low Nibble No Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD.
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> GND.
// MODULE.06 -> MCU.RA1.
// MODULE.07 -> NC.
// MODULE.08 -> NC.
// MODULE.09 -> NC.
// MODULE.10 -> NC.
// MODULE.11 -> MCU.RB0.
// MODULE.12 -> MCU.RB1.
// MODULE.13 -> MCU.RB2.
// MODULE.14 -> MCU.RB3.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_E										LATAbits.LATA1
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_E_TRIS									TRISAbits.TRISA1
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_clearDisplay(void);
void st7066u_initialize(void);
void st7066u_writeInstruction(char cData);
void st7066u_writeData(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom patterns";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;

	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x02);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_clearDisplay(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_writeInstruction(char cData)
{
	ST7066U_RS = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData>>4) & 0x0f);
	ST7066U_E = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0x0f);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeData(char cData)
{
	ST7066U_RS = 1;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData>>4) & 0x0f);
	ST7066U_E = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0x0f);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

4.String & Custom Patterns - 4-Bit Low Nibble With Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 4-Bit Low Nibble With Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD.
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> MCU.RA1.
// MODULE.06 -> MCU.RA2.
// MODULE.07 -> NC.
// MODULE.08 -> NC.
// MODULE.09 -> NC.
// MODULE.10 -> NC.
// MODULE.11 -> MCU.RB0.
// MODULE.12 -> MCU.RB1.
// MODULE.13 -> MCU.RB2.
// MODULE.14 -> MCU.RB3.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_DATA_BF									PORTBbits.RB3
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_RW										LATAbits.LATA1
#define ST7066U_E										LATAbits.LATA2
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_RW_TRIS									TRISAbits.TRISA1
#define ST7066U_E_TRIS									TRISAbits.TRISA2
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_clearDisplay(void);
void st7066u_initialize(void);
void st7066u_readBusyFlag(void);
void st7066u_writeInstruction(char cData);
void st7066u_writeInstructionNBF(char cData);
void st7066u_writeData(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom pattern";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_RW_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;

	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x02);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_clearDisplay(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_readBusyFlag(void)
{
	ST7066U_RS = 0;
	ST7066U_RW = 1;
	ST7066U_DATA &= 0xf0;
	ST7066U_DATA_TRIS = 0x0f;
	do{
		ST7066U_E = 0;
		ST7066U_E = 1;
	}while(ST7066U_DATA_BF);
	ST7066U_DATA &= 0xf0;
	ST7066U_DATA_TRIS = 0x00;
}

void st7066u_writeInstruction(char cData)
{
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData>>4) & 0x0f);
	ST7066U_E = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0x0f);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeInstructionNBF(char cData)
{
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData>>4) & 0x0f);
	ST7066U_E = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0x0f);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeData(char cData)
{
	ST7066U_RS = 1;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData>>4) & 0x0f);
	ST7066U_E = 0;
	ST7066U_DATA &= 0xf0;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0x0f);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

5.String & Custom Patterns - 4-Bit High Nibble No Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 4-Bit High Nibble No Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD                                         .
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> GND.
// MODULE.06 -> MCU.RA1.
// MODULE.07 -> NC.
// MODULE.08 -> NC.
// MODULE.09 -> NC.
// MODULE.10 -> NC.
// MODULE.11 -> MCU.RB4.
// MODULE.12 -> MCU.RB5.
// MODULE.13 -> MCU.RB6.
// MODULE.14 -> MCU.RB7.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_E										LATAbits.LATA1
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_E_TRIS									TRISAbits.TRISA1
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_clearDisplay(void);
void st7066u_initialize(void);
void st7066u_writeInstruction(char cData);
void st7066u_writeData(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom patterns";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;
	
	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x03);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_clearDisplay(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_writeInstruction(char cData)
{
	ST7066U_RS = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0xf0);
	ST7066U_E = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData<<4) & 0xf0);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeData(char cData)
{
	ST7066U_RS = 1;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0xf0);
	ST7066U_E = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData<<4) & 0xf0);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

6.String & Custom Patterns - 4-Bit High Nibble With Busy Flag.

// Configuration registers.
#pragma config IESO = OFF, FCMEN = OFF, OSC = INTIO7
#pragma config BORV = 3, BOREN = OFF, PWRT = OFF
#pragma config WDTPS = 32768, WDT = OFF
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC
#pragma config DEBUG = OFF, XINST = OFF, LVP = OFF, STVREN = ON
#pragma config CP3 = OFF, CP2 = OFF, CP1 = OFF, CP0 = OFF
#pragma config CPD = OFF, CPB = OFF
#pragma config WRT3 = OFF, WRT2 = OFF, WRT1 = OFF, WRT0 = OFF
#pragma config WRTD = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR3 = OFF, EBTR2 = OFF, EBTR1 = OFF, EBTR0 = OFF
#pragma config EBTRB = OFF

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 8000000
// PIC18F2620 - Compile with XC8(v2.00).
// PIC18F2620 - @8MHz Internal oscillator.

// LCD 4x20 - ST7066U (HD44780 Compatible) - 4-Bit High Nibble With Busy Flag.
// String & Custom Patterns.

// MODULE.01 -> GND.
// MODULE.02 -> VDD.
// MODULE.03 -> NC.
// MODULE.04 -> MCU.RA0.
// MODULE.05 -> MCU.RA1.
// MODULE.06 -> MCU.RA2.
// MODULE.07 -> NC.
// MODULE.08 -> NC.
// MODULE.09 -> NC.
// MODULE.10 -> NC.
// MODULE.11 -> MCU.RB4.
// MODULE.12 -> MCU.RB5.
// MODULE.13 -> MCU.RB6.
// MODULE.14 -> MCU.RB7.
// MODULE.15 -> NC.
// MODULE.16 -> GND.

// JP1 - SCL Not use.
// JP2 - SDA Not use.
// JP3 - VEE Close, use P3 for brightness.
// JP4 - BCKL Close.

// Definitions.
// ST7066U Commands Port & Data Port.
#define ST7066U_DATA									LATB
#define ST7066U_DATA_TRIS								TRISB
#define ST7066U_DATA_BF									PORTBbits.RB7
#define ST7066U_RS										LATAbits.LATA0
#define ST7066U_RW										LATAbits.LATA1
#define ST7066U_E										LATAbits.LATA2
#define ST7066U_RS_TRIS									TRISAbits.TRISA0
#define ST7066U_RW_TRIS									TRISAbits.TRISA1
#define ST7066U_E_TRIS									TRISAbits.TRISA2
// ST7066U Instructions.
#define ST7066U_CLEAR_DISPLAY							0x01
#define ST7066U_RETURN_HOME								0x02
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT		0x04
#define ST7066U_ENTRY_MODE_DDRAM_DECREMENT_SHIFT		0x05
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT		0x06
#define ST7066U_ENTRY_MODE_DDRAM_INCREMENT_SHIFT		0x07
#define ST7066U_DISPLAY_OFF								0x08
#define ST7066U_DISPLAY_ON_CURSOR_OFF					0x0C
#define ST7066U_DISPLAY_ON_CURSOR_ON_NOBLINK			0x0E
#define ST7066U_DISPLAY_ON_CURSOR_ON_BLINK				0x0F
#define ST7066U_DISPLAY_CURSOR_SHIFT_LEFT				0x10
#define ST7066U_DISPLAY_CURSOR_SHIFT_RIGHT				0x14
#define ST7066U_DISPLAY_SCREEN_SHIFT_LEFT				0x18
#define ST7066U_DISPLAY_SCREEN_SHIFT_RIGHT				0x1C
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x8		0x20
#define ST7066U_FUNCTION_SET_4_BIT_ONE_LINE_FONT5x11	0x24
#define ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8		0x28
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x8		0x30
#define ST7066U_FUNCTION_SET_8_BIT_ONE_LINE_FONT5x11	0x34
#define ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8		0x38
#define ST7066U_SET_CGRAM_ADDRESS						0x40
#define ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE			0x80
#define ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE			0xC0
#define ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE			0x94
#define ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE			0xD4

// Function prototypes.
void st7066u_busyFlag(void);
void st7066u_clearDisplay(void);
void st7066u_initialize(void);
void st7066u_writeInstruction(char cData);
void st7066u_writeInstructionNBF(char cData);
void st7066u_writeData(char cData);
void st7066u_writeString(const char * cData);
void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Custom patterns";
const char custom_patterns[5][8] = {
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
	{0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator 8MHz.
	OSCCONbits.IRCF2  = 1;
	OSCCONbits.IRCF1  = 1;
	OSCCONbits.IRCF0  = 1;
	OSCTUNEbits.PLLEN = 0;
	while(!OSCCONbits.IOFS);
	// Outputs for LCD command.
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_E = 0;
	ST7066U_RS_TRIS = 0;
	ST7066U_RW_TRIS = 0;
	ST7066U_E_TRIS = 0;
	// Outputs for LCD data.
	ST7066U_DATA = 0x00;
	ST7066U_DATA_TRIS = 0x00;
	
	st7066u_initialize();

	// Write 5x8 Dots Custom Patterns in ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			st7066u_writeData(custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	st7066u_writeStringSetCursor(string0, ST7066U_SET_DDRAM_ADDRESS_FIRST_LINE + 0x05);
	st7066u_writeStringSetCursor(string1, ST7066U_SET_DDRAM_ADDRESS_SECOND_LINE + 0x03);
	st7066u_writeStringSetCursor(string2, ST7066U_SET_DDRAM_ADDRESS_THIRD_LINE + 0x02);

	// Display Custom Patterns from ST7066U CGRAM.
	st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x05);
	st7066u_writeData(0x00);
	st7066u_writeData(0x01);
	st7066u_writeData(0x02);
	st7066u_writeData(0x03);
	st7066u_writeData(0x04);
	st7066u_writeString(" - ");
	
	while(1){
		for(pattern=0; pattern<5; pattern++){
			st7066u_writeInstruction(ST7066U_SET_DDRAM_ADDRESS_FOURTH_LINE + 0x0d);
			st7066u_writeData(pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void st7066u_busyFlag(void)
{
	ST7066U_RS = 0;
	ST7066U_RW = 1;
	ST7066U_DATA &= 0x0f;
	ST7066U_DATA_TRIS = 0xf0;
	do{
		ST7066U_E = 0;
		ST7066U_E = 1;
	}while(ST7066U_DATA_BF);
	ST7066U_DATA &= 0x0f;
	ST7066U_DATA_TRIS  = 0x00;
}

void st7066u_writeInstruction(char cData)
{
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0xf0);
	ST7066U_E = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData<<4) & 0xf0);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeInstructionNBF(char cData)
{
	ST7066U_RS = 0;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0xf0);
	ST7066U_E = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData<<4) & 0xf0);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_writeData(char cData)
{
	ST7066U_RS = 1;
	ST7066U_RW = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= (cData & 0xf0);
	ST7066U_E = 0;
	ST7066U_DATA &= 0x0f;
	ST7066U_E = 1;
	ST7066U_DATA |= ((cData<<4) & 0xf0);
	ST7066U_E = 0;
	__delay_us(40);
}

void st7066u_clearDisplay(void)
{
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
}

void st7066u_initialize(void)
{
	__delay_ms(50);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_8_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstructionNBF(ST7066U_FUNCTION_SET_4_BIT_TWO_LINE_FONT5x8);
	st7066u_writeInstruction(ST7066U_DISPLAY_ON_CURSOR_OFF);
	st7066u_writeInstruction(ST7066U_CLEAR_DISPLAY);
	__delay_ms(2);
	st7066u_writeInstruction(ST7066U_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT);
}

void st7066u_writeString(const char * cData)
{
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

void st7066u_writeStringSetCursor(const char * cData, uint8_t u8Data)
{
	st7066u_writeInstruction(u8Data);
	while(*cData != '\0')
		st7066u_writeData(*cData++);
}

08.2018