PIC8-Bit Trainer - Module LCD - EA-DOGS104-A - SSD1803A - 4x10.

0.Contents

PIC18F Trainer : PIC18F2620 @8MHz Internal oscillator.

1.String & Custom Patterns - 2 Lines Double Height - I2C, Controlled Backlight.

// Configuration register.
#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.

// TODO - RESET 1-50ms - 0-200us - 1.

// TODO - DEMO MODE - Ajouter des variables
// bottom / top view.
// ROM A / B / C.
// 4lines
// 1 Double Line, 2 Lines.
// 1 Line, 1 Double Line, 1 Line.
// 2 Lines, 1 Double Line.
// 2 Double Line.

// LCD EA-DOGS104-A 4x10 - SSD1803A - 2 Lines Double Height - I2C.
// String & Custom Patterns.
// Controlled Backlight.

// Expansion Module - EA-DOGS104-A - Rev.C.

// JP1 - SCL Close.
// JP2 - SDA Close.
// JP3 - VEE Not use.
// JP4 - BCKL Not use.

// Expansion Module.
// SA0 - 0x78 Close.

// Definitions.
// I2C Port.
#define I2C_SCL															LATCbits.LATC3
#define I2C_SDA															LATCbits.LATC4
#define I2C_SCL_TRIS													TRISCbits.TRISC3
#define I2C_SDA_TRIS													TRISCbits.TRISC4
// I2C.
#define I2C_WRITE														0x00
#define I2C_READ														0x01
// Backlight.
#define DOGM204A_BACKLIGHT												LATBbits.LATB0
#define DOGM204A_BACKLIGHT_TRIS											TRISBbits.TRISB0
// SSD1803A Address Select Bit A0.
#define SSD1803A_ADDRESS_78												0x78
#define SSD1803A_ADDRESS_7A												0x7A
#define SSD1803A_CONTROL_CONTINUOUS_COMMAND								0x00
#define SSD1803A_CONTROL_CONTINUOUS_DATA								0x40
#define SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND							0x80
#define SSD1803A_CONTROL_NO_CONTINUOUS_DATA								0xC0
// Extension Register RE = 0 & IS = 0.
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_LEFT							0x10
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_RIGHT							0x14
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_LEFT							0x18
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_RIGHT							0x1C
#define SSD1803A_FS0_SET_CGRAM_ADDRESS									0x40
// Extension Register RE = 0 & IS = 1.
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F00						0x10
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F01						0x11
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F00						0x12
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F01						0x13
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F00						0x14
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F01						0x15
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F00						0x16
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F01						0x17
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F00						0x18
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F01						0x19
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F00						0x1A
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F01						0x1B
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F00						0x1C
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F01						0x1D
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00						0x1E
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F01						0x1F
#define SSD1803A_FS1_SET_SEGRAM_ADDRESS									0x40
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_0							0x50
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_1							0x51
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_2							0x52
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_3							0x53
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_0							0x54
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_1							0x55
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_2							0x56
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3							0x57
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_0 							0x58
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_1							0x59
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_2							0x5A
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_3							0x5B
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_0							0x5C
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_1							0x5D
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_2							0x5E
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_3							0x5F
#define SSD1803A_FS1_FOLLOWER_CONTROL_OFF								0x60
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_0							0x68
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_1							0x69
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_2							0x6A
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_3							0x6B
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_4							0x6C
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_5							0x6D
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6							0x6E
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_7							0x6F
#define SSD1803A_FS1_CONTRAST_LSB_0										0x70
#define SSD1803A_FS1_CONTRAST_LSB_1										0x71
#define SSD1803A_FS1_CONTRAST_LSB_2										0x72
#define SSD1803A_FS1_CONTRAST_LSB_3										0x73
#define SSD1803A_FS1_CONTRAST_LSB_4										0x74
#define SSD1803A_FS1_CONTRAST_LSB_5										0x75
#define SSD1803A_FS1_CONTRAST_LSB_6										0x76
#define SSD1803A_FS1_CONTRAST_LSB_7										0x77
#define SSD1803A_FS1_CONTRAST_LSB_8										0x78
#define SSD1803A_FS1_CONTRAST_LSB_9										0x79
#define SSD1803A_FS1_CONTRAST_LSB_10									0x7A
#define SSD1803A_FS1_CONTRAST_LSB_11									0x7B
#define SSD1803A_FS1_CONTRAST_LSB_12									0x7C
#define SSD1803A_FS1_CONTRAST_LSB_13									0x7D
#define SSD1803A_FS1_CONTRAST_LSB_14									0x7E
#define SSD1803A_FS1_CONTRAST_LSB_15									0x7F
// Extension Register RE = 1 & IS = 0.
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH0					0x10
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH1					0x11
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0					0x12
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1					0x13
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH0					0x14
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH1					0x15
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH0					0x16
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1					0x17
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH0					0x18
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH1					0x19
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH0					0x1A
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1					0x1B
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH0					0x1C
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH1					0x1D
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH0					0x1E
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1					0x1F
// Extension Register RE = 1 & IS = 1.
#define SSD1803A_FS3_NOSHIFT											0x10
#define SSD1803A_FS3_SHIFT_LINE_1										0x11
#define SSD1803A_FS3_SHIFT_LINE_2										0x12
#define SSD1803A_FS3_SHIFT_LINE_12										0x13
#define SSD1803A_FS3_SHIFT_LINE_3										0x14
#define SSD1803A_FS3_SHIFT_LINE_13										0x15
#define SSD1803A_FS3_SHIFT_LINE_23										0x16
#define SSD1803A_FS3_SHIFT_LINE_123										0x17
#define SSD1803A_FS3_SHIFT_LINE_4										0x18
#define SSD1803A_FS3_SHIFT_LINE_14										0x19
#define SSD1803A_FS3_SHIFT_LINE_24										0x1A
#define SSD1803A_FS3_SHIFT_LINE_124										0x1B
#define SSD1803A_FS3_SHIFT_LINE_34										0x1C
#define SSD1803A_FS3_SHIFT_LINE_134										0x1D
#define SSD1803A_FS3_SHIFT_LINE_234										0x1E
#define SSD1803A_FS3_SHIFT_LINE_1234									0x1F
#define SSD1803A_FS3_NOSCROLL										 	0x10
#define SSD1803A_FS3_SCROLL_LINE_1										0x11
#define SSD1803A_FS3_SCROLL_LINE_2										0x12
#define SSD1803A_FS3_SCROLL_LINE_12										0x13
#define SSD1803A_FS3_SCROLL_LINE_3										0x14
#define SSD1803A_FS3_SCROLL_LINE_13										0x15
#define SSD1803A_FS3_SCROLL_LINE_23										0x16
#define SSD1803A_FS3_SCROLL_LINE_123									0x17
#define SSD1803A_FS3_SCROLL_LINE_4										0x18
#define SSD1803A_FS3_SCROLL_LINE_14										0x19
#define SSD1803A_FS3_SCROLL_LINE_24										0x1A
#define SSD1803A_FS3_SCROLL_LINE_124									0x1B
#define SSD1803A_FS3_SCROLL_LINE_34										0x1C
#define SSD1803A_FS3_SCROLL_LINE_134									0x1D
#define SSD1803A_FS3_SCROLL_LINE_234									0x1E
#define SSD1803A_FS3_SCROLL_LINE_1234									0x1F
// Extension Register RE = 0 & IS = x.
#define SSD1803A_FS01_RETURN_HOME										0x02
#define SSD1803A_FS01_DISPLAY_OFF										0x08
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF								0x0C
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_NOBLINK						0x0E
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_BLINK						0x0F
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS0			0x20
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS1			0x21
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS0			0x24
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS1			0x25
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS0			0x28
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS1			0x29
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS0			0x2C
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS1			0x2D
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS0			0x30
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS1			0x31
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS0			0x34
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS1			0x35
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0			0x38
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1			0x39
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0			0x3C
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1			0x3D
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE				0x80
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE				0xA0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FIRST_LINE					0x8A
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_SECOND_LINE					0xAA
// Extension Register RE = 1 & IS = x.
#define SSD1803A_FS23_POWER_DOWN_OFF									0x02
#define SSD1803A_FS23_POWER_DOWN_ON										0x03
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW_MIRROR					0x04
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW							0x05
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW						0x06
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW_MIRROR					0x07
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_12LINE	0x08
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE	0x09
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_12LINE		0x0A
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_34LINE		0x0B
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_12LINE	0x0C
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_34LINE	0x0D
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_12LINE		0x0E
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_34LINE		0x0F
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_NORMAL			0x22
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_REVERSE			0x23
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_NORMAL			0x26
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_REVERSE			0x27
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_NORMAL			0x2A
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_REVERSE			0x2B
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_NORMAL			0x2E
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_REVERSE			0x2F
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_NORMAL			0x32
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_REVERSE			0x33
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_NORMAL			0x36
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_REVERSE			0x37
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL			0x3A
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_REVERSE			0x3B
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_NORMAL			0x3E
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_REVERSE			0x3F
#define SSD1803A_FS23_SCROLL_QUANTITY									0x80
#define SSD1803A_FS23_TEMPERATURE_COEFFICIENT							0x76
#define SSD1803A_FS23_ROM_SELECTION_COMMAND								0x72
// Extension Register RE = x & IS = x.
#define SSD1803A_FS0123_CLEAR_DISPLAY									0x01
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT				0x04
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_SHIFT				0x05
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT				0x06
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_SHIFT				0x07
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_005					0x02
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_010					0x04
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_015					0x06
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_020					0x07
#define SSD1803A_FS0123_ROM_SELECTION_A									0x00
#define SSD1803A_FS0123_ROM_SELECTION_B									0x04
#define SSD1803A_FS0123_ROM_SELECTION_C									0x08

// Function prototypes.
void i2c_initializeMaster(void);
uint8_t i2c_read(void);
void i2c_restart(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write(uint8_t u8Data);
void ssd1803a_clearDisplay(uint8_t u8Address);
void ssd1803a_initialize(uint8_t u8Address);
void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data);
void ssd1803a_writeData(uint8_t u8Address, char cData);
void ssd1803a_writeInstruction(uint8_t u8Address, char cData);
void ssd1803a_writeString(uint8_t u8Address, const char * cData);
void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
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);
	// I2C Port.
	I2C_SDA = 0;
	I2C_SCL = 0;
	I2C_SDA_TRIS = 1;
	I2C_SCL_TRIS = 1;
	// Output for Backlight.
	DOGM204A_BACKLIGHT = 1;
	DOGM204A_BACKLIGHT_TRIS = 0;

	i2c_initializeMaster();
	ssd1803a_initialize(SSD1803A_ADDRESS_78);
	ssd1803a_romSelection(SSD1803A_ADDRESS_78, SSD1803A_FS0123_ROM_SELECTION_A);

	// Write 5x8 Dots Custom Patterns in SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS0_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			ssd1803a_writeData(SSD1803A_ADDRESS_78, custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string0, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE);

	// Display Custom Patterns from SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x00);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x01);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x02);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x03);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x04);
	ssd1803a_writeString(SSD1803A_ADDRESS_78, " - ");

	while(1){
		for(pattern=0; pattern<5; pattern++){
		ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE + 0x08);
			ssd1803a_writeData(SSD1803A_ADDRESS_78, pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void i2c_initializeMaster(void)
{
	// I2C - Master.
	SSPSTAT = 0x80;
	SSPCON1 = 0x28;
	SSPCON2 = 0x00;
	// SSPADD = 0x03 ~400kHz @8MHz.
	// SSPADD = 0x12 ~100kHz @8MHz.
	SSPADD = 0x12;
}

void i2c_restart(void)
{
	SSPCON2bits.RSEN = 1;
	while(SSPCON2bits.RSEN);
}

void i2c_start(void)
{
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
}

void i2c_stop(void)
{
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
}

void i2c_write(uint8_t u8Data)
{
	PIR1bits.SSPIF = 0;
	SSPBUF = u8Data;
	while(!PIR1bits.SSPIF);
	while(SSPCON2bits.ACKSTAT);
}

void ssd1803a_clearDisplay(uint8_t u8Address)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS0123_CLEAR_DISPLAY);
	__delay_ms(2);
}

void ssd1803a_initialize(uint8_t u8Address)
{
	__delay_ms(50);

	i2c_start();
	i2c_write(SSD1803A_ADDRESS_78);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_COMMAND);
	i2c_write(SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	i2c_write(SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE);
	i2c_write(SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW);
	i2c_write(SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00);
	i2c_write(SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1);
	i2c_write(SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6);
	i2c_write(SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3);
	i2c_write(SSD1803A_FS1_CONTRAST_LSB_10);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
	i2c_write(SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF);
	i2c_write(SSD1803A_FS0123_CLEAR_DISPLAY);
	i2c_stop();
	__delay_ms(2);
}

void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_ROM_SELECTION_COMMAND);
	ssd1803a_writeData(u8Address, u8Data);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
}

void ssd1803a_writeData(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_DATA);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeInstruction(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeString(uint8_t u8Address, const char * cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(u8Data);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

2.String & Custom Patterns - 3 Lines Double Height TOP - I2C, Controlled Backlight.

// Configuration register.
#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.

// TODO - RESET 1-50ms - 0-200us - 1.

// TODO - DEMO MODE - Ajouter des variables
// bottom / top view.
// ROM A / B / C.
// 4lines
// 1 Double Line, 2 Lines.
// 1 Line, 1 Double Line, 1 Line.
// 2 Lines, 1 Double Line.
// 2 Double Line.

// LCD EA-DOGS104-A 4x10 - SSD1803A - 3 Lines Double Height MIDDLE - I2C.
// String & Custom Patterns.
// Controlled Backlight.

// Expansion Module - EA-DOGS104-A - Rev.B.

// JP1 - SCL Close.
// JP2 - SDA Close.
// JP3 - VEE Not use.
// JP4 - BCKL Not use.

// Expansion Module.
// SA0 - 0x78 Close.

// Definitions.
// I2C Port.
#define I2C_SCL															LATCbits.LATC3
#define I2C_SDA															LATCbits.LATC4
#define I2C_SCL_TRIS													TRISCbits.TRISC3
#define I2C_SDA_TRIS													TRISCbits.TRISC4
// I2C.
#define I2C_WRITE														0x00
#define I2C_READ														0x01
// DOGM204 Port.
#define DOGS104_RESET													LATBbits.LATB1
#define DOGS104_RESET_TRIS												TRISBbits.TRISB1
// Backlight.
#define DOGM204A_BACKLIGHT												LATBbits.LATB0
#define DOGM204A_BACKLIGHT_TRIS											TRISBbits.TRISB0
// SSD1803A Address Select Bit A0.
#define SSD1803A_ADDRESS_78												0x78
#define SSD1803A_ADDRESS_7A												0x7A
#define SSD1803A_CONTROL_CONTINUOUS_COMMAND								0x00
#define SSD1803A_CONTROL_CONTINUOUS_DATA								0x40
#define SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND							0x80
#define SSD1803A_CONTROL_NO_CONTINUOUS_DATA								0xC0
// Extension Register RE = 0 & IS = 0.
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_LEFT							0x10
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_RIGHT							0x14
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_LEFT							0x18
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_RIGHT							0x1C
#define SSD1803A_FS0_SET_CGRAM_ADDRESS									0x40
// Extension Register RE = 0 & IS = 1.
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F00						0x10
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F01						0x11
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F00						0x12
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F01						0x13
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F00						0x14
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F01						0x15
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F00						0x16
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F01						0x17
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F00						0x18
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F01						0x19
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F00						0x1A
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F01						0x1B
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F00						0x1C
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F01						0x1D
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00						0x1E
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F01						0x1F
#define SSD1803A_FS1_SET_SEGRAM_ADDRESS									0x40
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_0							0x50
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_1							0x51
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_2							0x52
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_3							0x53
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_0							0x54
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_1							0x55
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_2							0x56
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3							0x57
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_0 							0x58
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_1							0x59
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_2							0x5A
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_3							0x5B
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_0							0x5C
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_1							0x5D
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_2							0x5E
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_3							0x5F
#define SSD1803A_FS1_FOLLOWER_CONTROL_OFF								0x60
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_0							0x68
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_1							0x69
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_2							0x6A
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_3							0x6B
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_4							0x6C
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_5							0x6D
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6							0x6E
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_7							0x6F
#define SSD1803A_FS1_CONTRAST_LSB_0										0x70
#define SSD1803A_FS1_CONTRAST_LSB_1										0x71
#define SSD1803A_FS1_CONTRAST_LSB_2										0x72
#define SSD1803A_FS1_CONTRAST_LSB_3										0x73
#define SSD1803A_FS1_CONTRAST_LSB_4										0x74
#define SSD1803A_FS1_CONTRAST_LSB_5										0x75
#define SSD1803A_FS1_CONTRAST_LSB_6										0x76
#define SSD1803A_FS1_CONTRAST_LSB_7										0x77
#define SSD1803A_FS1_CONTRAST_LSB_8										0x78
#define SSD1803A_FS1_CONTRAST_LSB_9										0x79
#define SSD1803A_FS1_CONTRAST_LSB_10									0x7A
#define SSD1803A_FS1_CONTRAST_LSB_11									0x7B
#define SSD1803A_FS1_CONTRAST_LSB_12									0x7C
#define SSD1803A_FS1_CONTRAST_LSB_13									0x7D
#define SSD1803A_FS1_CONTRAST_LSB_14									0x7E
#define SSD1803A_FS1_CONTRAST_LSB_15									0x7F
// Extension Register RE = 1 & IS = 0.
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH0					0x10
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH1					0x11
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0					0x12
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1					0x13
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH0					0x14
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH1					0x15
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH0					0x16
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1					0x17
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH0					0x18
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH1					0x19
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH0					0x1A
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1					0x1B
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH0					0x1C
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH1					0x1D
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH0					0x1E
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1					0x1F
// Extension Register RE = 1 & IS = 1.
#define SSD1803A_FS3_NOSHIFT											0x10
#define SSD1803A_FS3_SHIFT_LINE_1										0x11
#define SSD1803A_FS3_SHIFT_LINE_2										0x12
#define SSD1803A_FS3_SHIFT_LINE_12										0x13
#define SSD1803A_FS3_SHIFT_LINE_3										0x14
#define SSD1803A_FS3_SHIFT_LINE_13										0x15
#define SSD1803A_FS3_SHIFT_LINE_23										0x16
#define SSD1803A_FS3_SHIFT_LINE_123										0x17
#define SSD1803A_FS3_SHIFT_LINE_4										0x18
#define SSD1803A_FS3_SHIFT_LINE_14										0x19
#define SSD1803A_FS3_SHIFT_LINE_24										0x1A
#define SSD1803A_FS3_SHIFT_LINE_124										0x1B
#define SSD1803A_FS3_SHIFT_LINE_34										0x1C
#define SSD1803A_FS3_SHIFT_LINE_134										0x1D
#define SSD1803A_FS3_SHIFT_LINE_234										0x1E
#define SSD1803A_FS3_SHIFT_LINE_1234									0x1F
#define SSD1803A_FS3_NOSCROLL										 	0x10
#define SSD1803A_FS3_SCROLL_LINE_1										0x11
#define SSD1803A_FS3_SCROLL_LINE_2										0x12
#define SSD1803A_FS3_SCROLL_LINE_12										0x13
#define SSD1803A_FS3_SCROLL_LINE_3										0x14
#define SSD1803A_FS3_SCROLL_LINE_13										0x15
#define SSD1803A_FS3_SCROLL_LINE_23										0x16
#define SSD1803A_FS3_SCROLL_LINE_123									0x17
#define SSD1803A_FS3_SCROLL_LINE_4										0x18
#define SSD1803A_FS3_SCROLL_LINE_14										0x19
#define SSD1803A_FS3_SCROLL_LINE_24										0x1A
#define SSD1803A_FS3_SCROLL_LINE_124									0x1B
#define SSD1803A_FS3_SCROLL_LINE_34										0x1C
#define SSD1803A_FS3_SCROLL_LINE_134									0x1D
#define SSD1803A_FS3_SCROLL_LINE_234									0x1E
#define SSD1803A_FS3_SCROLL_LINE_1234									0x1F
// Extension Register RE = 0 & IS = x.
#define SSD1803A_FS01_RETURN_HOME										0x02
#define SSD1803A_FS01_DISPLAY_OFF										0x08
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF								0x0C
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_NOBLINK						0x0E
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_BLINK						0x0F
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS0			0x20
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS1			0x21
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS0			0x24
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS1			0x25
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS0			0x28
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS1			0x29
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS0			0x2C
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS1			0x2D
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS0			0x30
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS1			0x31
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS0			0x34
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS1           0x35
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0			0x38
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1			0x39
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0			0x3C
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1			0x3D
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE				0x80
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE				0xA0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE				0xC0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FIRST_LINE					0x8A
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_SECOND_LINE					0xAA
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_THIRD_LINE					0xCA
// Extension Register RE = 1 & IS = x.
#define SSD1803A_FS23_POWER_DOWN_OFF									0x02
#define SSD1803A_FS23_POWER_DOWN_ON										0x03
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW_MIRROR					0x04
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW							0x05
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW						0x06
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW_MIRROR					0x07
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_12LINE	0x08
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE	0x09
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_12LINE		0x0A
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_34LINE		0x0B
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_12LINE	0x0C
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_34LINE	0x0D
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_12LINE		0x0E
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_34LINE		0x0F
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_NORMAL			0x22
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_REVERSE			0x23
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_NORMAL			0x26
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_REVERSE			0x27
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_NORMAL			0x2A
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_REVERSE			0x2B
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_NORMAL			0x2E
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_REVERSE			0x2F
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_NORMAL			0x32
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_REVERSE			0x33
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_NORMAL			0x36
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_REVERSE			0x37
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL			0x3A
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_REVERSE			0x3B
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_NORMAL			0x3E
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_REVERSE			0x3F
#define SSD1803A_FS23_SCROLL_QUANTITY									0x80
#define SSD1803A_FS23_TEMPERATURE_COEFFICIENT							0x76
#define SSD1803A_FS23_ROM_SELECTION_COMMAND								0x72
// Extension Register RE = x & IS = x.
#define SSD1803A_FS0123_CLEAR_DISPLAY									0x01
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT				0x04
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_SHIFT				0x05
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT				0x06
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_SHIFT				0x07
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_005					0x02
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_010					0x04
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_015					0x06
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_020					0x07
#define SSD1803A_FS0123_ROM_SELECTION_A									0x00
#define SSD1803A_FS0123_ROM_SELECTION_B									0x04
#define SSD1803A_FS0123_ROM_SELECTION_C									0x08

// Function prototypes.
void i2c_initializeMaster(void);
uint8_t i2c_read(void);
void i2c_restart(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write(uint8_t u8Data);
void ssd1803a_clearDisplay(uint8_t u8Address);
void ssd1803a_initialize(uint8_t u8Address);
void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data);
void ssd1803a_writeData(uint8_t u8Address, char cData);
void ssd1803a_writeInstruction(uint8_t u8Address, char cData);
void ssd1803a_writeString(uint8_t u8Address, const char * cData);
void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "tronix.io";
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);
	// I2C Port.
	I2C_SDA = 0;
	I2C_SCL = 0;
	I2C_SDA_TRIS = 1;
	I2C_SCL_TRIS = 1;
	DOGS104_RESET = 0;
	DOGS104_RESET_TRIS = 0;
	// Output for Backlight.
	DOGM204A_BACKLIGHT = 1;
	DOGM204A_BACKLIGHT_TRIS = 0;

	i2c_initializeMaster();
	ssd1803a_initialize(SSD1803A_ADDRESS_78);
	ssd1803a_romSelection(SSD1803A_ADDRESS_78, SSD1803A_FS0123_ROM_SELECTION_A);

	// Write 5x8 Dots Custom Patterns in SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS0_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			ssd1803a_writeData(SSD1803A_ADDRESS_78, custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string0, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE);
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string1, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE);

	// Display Custom Patterns from SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x00);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x01);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x02);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x03);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x04);
	ssd1803a_writeString(SSD1803A_ADDRESS_78, " - ");

	while(1){
		for(pattern=0; pattern<5; pattern++){
		ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE + 0x08);
			ssd1803a_writeData(SSD1803A_ADDRESS_78, pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void i2c_initializeMaster(void)
{
	// I2C - Master.
	SSPSTAT = 0x80;
	SSPCON1 = 0x28;
	SSPCON2 = 0x00;
	// SSPADD = 0x03 ~400kHz @8MHz.
	// SSPADD = 0x12 ~100kHz @8MHz.
	SSPADD = 0x12;
}

void i2c_restart(void)
{
	SSPCON2bits.RSEN = 1;
	while(SSPCON2bits.RSEN);
}

void i2c_start(void)
{
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
}

void i2c_stop(void)
{
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
}

void i2c_write(uint8_t u8Data)
{
	PIR1bits.SSPIF = 0;
	SSPBUF = u8Data;
	while(!PIR1bits.SSPIF);
	while(SSPCON2bits.ACKSTAT);
}

void ssd1803a_clearDisplay(uint8_t u8Address)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS0123_CLEAR_DISPLAY);
	__delay_ms(2);
}

void ssd1803a_initialize(uint8_t u8Address)
{
	__delay_ms(5);
	DOGS104_RESET = 1;
	__delay_ms(10);

	i2c_start();
	i2c_write(SSD1803A_ADDRESS_78);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_COMMAND);
	i2c_write(SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	i2c_write(SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE);
	i2c_write(SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW);
	i2c_write(SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00);
	i2c_write(SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1);
	i2c_write(SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6);
	i2c_write(SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3);
	i2c_write(SSD1803A_FS1_CONTRAST_LSB_10);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
	i2c_write(SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF);
	i2c_write(SSD1803A_FS0123_CLEAR_DISPLAY);
	i2c_stop();
	__delay_ms(2);
}

void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_ROM_SELECTION_COMMAND);
	ssd1803a_writeData(u8Address, u8Data);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
}

void ssd1803a_writeData(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_DATA);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeInstruction(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeString(uint8_t u8Address, const char * cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(u8Data);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

3.String & Custom Patterns - 3 Lines Double Height MIDDLE - I2C, Controlled Backlight.

// Configuration register.
#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.

// TODO - RESET 1-50ms - 0-200us - 1.

// TODO - DEMO MODE - Ajouter des variables
// bottom / top view.
// ROM A / B / C.
// 4lines
// 1 Double Line, 2 Lines.
// 1 Line, 1 Double Line, 1 Line.
// 2 Lines, 1 Double Line.
// 2 Double Line.

// LCD EA-DOGS104-A 4x10 - SSD1803A - 3 Lines Double Height MIDDLE - I2C.
// String & Custom Patterns.
// Controlled Backlight.

// Expansion Module - EA-DOGS104-A - Rev.B.

// JP1 - SCL Close.
// JP2 - SDA Close.
// JP3 - VEE Not use.
// JP4 - BCKL Not use.

// Expansion Module.
// SA0 - 0x78 Close.

// Definitions.
// I2C Port.
#define I2C_SCL															LATCbits.LATC3
#define I2C_SDA															LATCbits.LATC4
#define I2C_SCL_TRIS													TRISCbits.TRISC3
#define I2C_SDA_TRIS													TRISCbits.TRISC4
// I2C.
#define I2C_WRITE														0x00
#define I2C_READ														0x01
// DOGM204 Port.
#define DOGS104_RESET													LATBbits.LATB1
#define DOGS104_RESET_TRIS												TRISBbits.TRISB1
// Backlight.
#define DOGM204A_BACKLIGHT												LATBbits.LATB0
#define DOGM204A_BACKLIGHT_TRIS											TRISBbits.TRISB0
// SSD1803A Address Select Bit A0.
#define SSD1803A_ADDRESS_78												0x78
#define SSD1803A_ADDRESS_7A												0x7A
#define SSD1803A_CONTROL_CONTINUOUS_COMMAND								0x00
#define SSD1803A_CONTROL_CONTINUOUS_DATA								0x40
#define SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND							0x80
#define SSD1803A_CONTROL_NO_CONTINUOUS_DATA								0xC0
// Extension Register RE = 0 & IS = 0.
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_LEFT							0x10
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_RIGHT							0x14
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_LEFT							0x18
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_RIGHT							0x1C
#define SSD1803A_FS0_SET_CGRAM_ADDRESS									0x40
// Extension Register RE = 0 & IS = 1.
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F00						0x10
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F01						0x11
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F00						0x12
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F01						0x13
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F00						0x14
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F01						0x15
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F00						0x16
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F01						0x17
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F00						0x18
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F01						0x19
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F00						0x1A
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F01						0x1B
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F00						0x1C
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F01						0x1D
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00						0x1E
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F01						0x1F
#define SSD1803A_FS1_SET_SEGRAM_ADDRESS									0x40
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_0							0x50
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_1							0x51
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_2							0x52
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_3							0x53
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_0							0x54
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_1							0x55
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_2							0x56
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3							0x57
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_0 							0x58
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_1							0x59
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_2							0x5A
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_3							0x5B
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_0							0x5C
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_1							0x5D
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_2							0x5E
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_3							0x5F
#define SSD1803A_FS1_FOLLOWER_CONTROL_OFF								0x60
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_0							0x68
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_1							0x69
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_2							0x6A
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_3							0x6B
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_4							0x6C
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_5							0x6D
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6							0x6E
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_7							0x6F
#define SSD1803A_FS1_CONTRAST_LSB_0										0x70
#define SSD1803A_FS1_CONTRAST_LSB_1										0x71
#define SSD1803A_FS1_CONTRAST_LSB_2										0x72
#define SSD1803A_FS1_CONTRAST_LSB_3										0x73
#define SSD1803A_FS1_CONTRAST_LSB_4										0x74
#define SSD1803A_FS1_CONTRAST_LSB_5										0x75
#define SSD1803A_FS1_CONTRAST_LSB_6										0x76
#define SSD1803A_FS1_CONTRAST_LSB_7										0x77
#define SSD1803A_FS1_CONTRAST_LSB_8										0x78
#define SSD1803A_FS1_CONTRAST_LSB_9										0x79
#define SSD1803A_FS1_CONTRAST_LSB_10									0x7A
#define SSD1803A_FS1_CONTRAST_LSB_11									0x7B
#define SSD1803A_FS1_CONTRAST_LSB_12									0x7C
#define SSD1803A_FS1_CONTRAST_LSB_13									0x7D
#define SSD1803A_FS1_CONTRAST_LSB_14									0x7E
#define SSD1803A_FS1_CONTRAST_LSB_15									0x7F
// Extension Register RE = 1 & IS = 0.
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH0					0x10
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH1					0x11
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0					0x12
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1					0x13
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH0					0x14
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH1					0x15
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH0					0x16
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1					0x17
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH0					0x18
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH1					0x19
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH0					0x1A
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1					0x1B
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH0					0x1C
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH1					0x1D
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH0					0x1E
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1					0x1F
// Extension Register RE = 1 & IS = 1.
#define SSD1803A_FS3_NOSHIFT											0x10
#define SSD1803A_FS3_SHIFT_LINE_1										0x11
#define SSD1803A_FS3_SHIFT_LINE_2										0x12
#define SSD1803A_FS3_SHIFT_LINE_12										0x13
#define SSD1803A_FS3_SHIFT_LINE_3										0x14
#define SSD1803A_FS3_SHIFT_LINE_13										0x15
#define SSD1803A_FS3_SHIFT_LINE_23										0x16
#define SSD1803A_FS3_SHIFT_LINE_123										0x17
#define SSD1803A_FS3_SHIFT_LINE_4										0x18
#define SSD1803A_FS3_SHIFT_LINE_14										0x19
#define SSD1803A_FS3_SHIFT_LINE_24										0x1A
#define SSD1803A_FS3_SHIFT_LINE_124										0x1B
#define SSD1803A_FS3_SHIFT_LINE_34										0x1C
#define SSD1803A_FS3_SHIFT_LINE_134										0x1D
#define SSD1803A_FS3_SHIFT_LINE_234										0x1E
#define SSD1803A_FS3_SHIFT_LINE_1234									0x1F
#define SSD1803A_FS3_NOSCROLL										 	0x10
#define SSD1803A_FS3_SCROLL_LINE_1										0x11
#define SSD1803A_FS3_SCROLL_LINE_2										0x12
#define SSD1803A_FS3_SCROLL_LINE_12										0x13
#define SSD1803A_FS3_SCROLL_LINE_3										0x14
#define SSD1803A_FS3_SCROLL_LINE_13										0x15
#define SSD1803A_FS3_SCROLL_LINE_23										0x16
#define SSD1803A_FS3_SCROLL_LINE_123									0x17
#define SSD1803A_FS3_SCROLL_LINE_4										0x18
#define SSD1803A_FS3_SCROLL_LINE_14										0x19
#define SSD1803A_FS3_SCROLL_LINE_24										0x1A
#define SSD1803A_FS3_SCROLL_LINE_124									0x1B
#define SSD1803A_FS3_SCROLL_LINE_34										0x1C
#define SSD1803A_FS3_SCROLL_LINE_134									0x1D
#define SSD1803A_FS3_SCROLL_LINE_234									0x1E
#define SSD1803A_FS3_SCROLL_LINE_1234									0x1F
// Extension Register RE = 0 & IS = x.
#define SSD1803A_FS01_RETURN_HOME										0x02
#define SSD1803A_FS01_DISPLAY_OFF										0x08
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF								0x0C
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_NOBLINK						0x0E
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_BLINK						0x0F
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS0			0x20
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS1			0x21
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS0			0x24
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS1			0x25
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS0			0x28
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS1			0x29
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS0			0x2C
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS1			0x2D
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS0			0x30
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS1			0x31
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS0			0x34
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS1           0x35
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0			0x38
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1			0x39
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0			0x3C
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1			0x3D
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE				0x80
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE				0xA0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE				0xC0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FIRST_LINE					0x8A
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_SECOND_LINE					0xAA
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_THIRD_LINE					0xCA
// Extension Register RE = 1 & IS = x.
#define SSD1803A_FS23_POWER_DOWN_OFF									0x02
#define SSD1803A_FS23_POWER_DOWN_ON										0x03
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW_MIRROR					0x04
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW							0x05
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW						0x06
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW_MIRROR					0x07
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_12LINE	0x08
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE	0x09
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_12LINE		0x0A
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_34LINE		0x0B
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_12LINE	0x0C
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_34LINE	0x0D
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_12LINE		0x0E
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_34LINE		0x0F
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_NORMAL			0x22
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_REVERSE			0x23
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_NORMAL			0x26
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_REVERSE			0x27
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_NORMAL			0x2A
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_REVERSE			0x2B
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_NORMAL			0x2E
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_REVERSE			0x2F
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_NORMAL			0x32
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_REVERSE			0x33
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_NORMAL			0x36
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_REVERSE			0x37
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL			0x3A
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_REVERSE			0x3B
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_NORMAL			0x3E
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_REVERSE			0x3F
#define SSD1803A_FS23_SCROLL_QUANTITY									0x80
#define SSD1803A_FS23_TEMPERATURE_COEFFICIENT							0x76
#define SSD1803A_FS23_ROM_SELECTION_COMMAND								0x72
// Extension Register RE = x & IS = x.
#define SSD1803A_FS0123_CLEAR_DISPLAY									0x01
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT				0x04
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_SHIFT				0x05
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT				0x06
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_SHIFT				0x07
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_005					0x02
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_010					0x04
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_015					0x06
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_020					0x07
#define SSD1803A_FS0123_ROM_SELECTION_A									0x00
#define SSD1803A_FS0123_ROM_SELECTION_B									0x04
#define SSD1803A_FS0123_ROM_SELECTION_C									0x08

// Function prototypes.
void i2c_initializeMaster(void);
uint8_t i2c_read(void);
void i2c_restart(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write(uint8_t u8Data);
void ssd1803a_clearDisplay(uint8_t u8Address);
void ssd1803a_initialize(uint8_t u8Address);
void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data);
void ssd1803a_writeData(uint8_t u8Address, char cData);
void ssd1803a_writeInstruction(uint8_t u8Address, char cData);
void ssd1803a_writeString(uint8_t u8Address, const char * cData);
void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "tronix.io";
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);
	// I2C Port.
	I2C_SDA = 0;
	I2C_SCL = 0;
	I2C_SDA_TRIS = 1;
	I2C_SCL_TRIS = 1;
	DOGS104_RESET = 0;
	DOGS104_RESET_TRIS = 0;
	// Output for Backlight.
	DOGM204A_BACKLIGHT = 1;
	DOGM204A_BACKLIGHT_TRIS = 0;

	i2c_initializeMaster();
	ssd1803a_initialize(SSD1803A_ADDRESS_78);
	ssd1803a_romSelection(SSD1803A_ADDRESS_78, SSD1803A_FS0123_ROM_SELECTION_A);

	// Write 5x8 Dots Custom Patterns in SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS0_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			ssd1803a_writeData(SSD1803A_ADDRESS_78, custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string0, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE);
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string1, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE);

	// Display Custom Patterns from SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x00);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x01);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x02);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x03);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x04);
	ssd1803a_writeString(SSD1803A_ADDRESS_78, " - ");

	while(1){
		for(pattern=0; pattern<5; pattern++){
		ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE + 0x08);
			ssd1803a_writeData(SSD1803A_ADDRESS_78, pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void i2c_initializeMaster(void)
{
	// I2C - Master.
	SSPSTAT = 0x80;
	SSPCON1 = 0x28;
	SSPCON2 = 0x00;
	// SSPADD = 0x03 ~400kHz @8MHz.
	// SSPADD = 0x12 ~100kHz @8MHz.
	SSPADD = 0x12;
}

void i2c_restart(void)
{
	SSPCON2bits.RSEN = 1;
	while(SSPCON2bits.RSEN);
}

void i2c_start(void)
{
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
}

void i2c_stop(void)
{
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
}

void i2c_write(uint8_t u8Data)
{
	PIR1bits.SSPIF = 0;
	SSPBUF = u8Data;
	while(!PIR1bits.SSPIF);
	while(SSPCON2bits.ACKSTAT);
}

void ssd1803a_clearDisplay(uint8_t u8Address)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS0123_CLEAR_DISPLAY);
	__delay_ms(2);
}

void ssd1803a_initialize(uint8_t u8Address)
{
	__delay_ms(5);
	DOGS104_RESET = 1;
	__delay_ms(10);

	i2c_start();
	i2c_write(SSD1803A_ADDRESS_78);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_COMMAND);
	i2c_write(SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	i2c_write(SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE);
	i2c_write(SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW);
	i2c_write(SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00);
	i2c_write(SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1);
	i2c_write(SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6);
	i2c_write(SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3);
	i2c_write(SSD1803A_FS1_CONTRAST_LSB_10);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
	i2c_write(SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF);
	i2c_write(SSD1803A_FS0123_CLEAR_DISPLAY);
	i2c_stop();
	__delay_ms(2);
}

void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_ROM_SELECTION_COMMAND);
	ssd1803a_writeData(u8Address, u8Data);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
}

void ssd1803a_writeData(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_DATA);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeInstruction(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeString(uint8_t u8Address, const char * cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(u8Data);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

4.String & Custom Patterns - 3 Lines Double Height BOTTOM - I2C, Controlled Backlight.

// Configuration register.
#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.

// TODO - RESET 1-50ms - 0-200us - 1.

// TODO - DEMO MODE - Ajouter des variables
// bottom / top view.
// ROM A / B / C.
// 4lines
// 1 Double Line, 2 Lines.
// 1 Line, 1 Double Line, 1 Line.
// 2 Lines, 1 Double Line.
// 2 Double Line.

// LCD EA-DOGS104-A 4x10 - SSD1803A - 3 Lines Double Height BOTTOM - I2C.
// String & Custom Patterns.
// Controlled Backlight.

// Expansion Module - EA-DOGS104-A - Rev.C.

// JP1 - SCL Close.
// JP2 - SDA Close.
// JP3 - VEE Not use.
// JP4 - BCKL Not use.

// Expansion Module.
// SA0 - 0x78 Close.

// Definitions.
// I2C Port.
#define I2C_SCL															LATCbits.LATC3
#define I2C_SDA															LATCbits.LATC4
#define I2C_SCL_TRIS													TRISCbits.TRISC3
#define I2C_SDA_TRIS													TRISCbits.TRISC4
// I2C.
#define I2C_WRITE														0x00
#define I2C_READ														0x01
// Backlight.
#define DOGM204A_BACKLIGHT												LATBbits.LATB0
#define DOGM204A_BACKLIGHT_TRIS											TRISBbits.TRISB0
// SSD1803A Address Select Bit A0.
#define SSD1803A_ADDRESS_78												0x78
#define SSD1803A_ADDRESS_7A												0x7A
#define SSD1803A_CONTROL_CONTINUOUS_COMMAND								0x00
#define SSD1803A_CONTROL_CONTINUOUS_DATA								0x40
#define SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND							0x80
#define SSD1803A_CONTROL_NO_CONTINUOUS_DATA								0xC0
// Extension Register RE = 0 & IS = 0.
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_LEFT							0x10
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_RIGHT							0x14
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_LEFT							0x18
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_RIGHT							0x1C
#define SSD1803A_FS0_SET_CGRAM_ADDRESS									0x40
// Extension Register RE = 0 & IS = 1.
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F00						0x10
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F01						0x11
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F00						0x12
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F01						0x13
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F00						0x14
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F01						0x15
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F00						0x16
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F01						0x17
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F00						0x18
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F01						0x19
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F00						0x1A
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F01						0x1B
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F00						0x1C
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F01						0x1D
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00						0x1E
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F01						0x1F
#define SSD1803A_FS1_SET_SEGRAM_ADDRESS									0x40
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_0							0x50
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_1							0x51
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_2							0x52
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_3							0x53
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_0							0x54
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_1							0x55
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_2							0x56
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3							0x57
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_0 							0x58
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_1							0x59
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_2							0x5A
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_3							0x5B
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_0							0x5C
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_1							0x5D
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_2							0x5E
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_3							0x5F
#define SSD1803A_FS1_FOLLOWER_CONTROL_OFF								0x60
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_0							0x68
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_1							0x69
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_2							0x6A
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_3							0x6B
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_4							0x6C
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_5							0x6D
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6							0x6E
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_7							0x6F
#define SSD1803A_FS1_CONTRAST_LSB_0										0x70
#define SSD1803A_FS1_CONTRAST_LSB_1										0x71
#define SSD1803A_FS1_CONTRAST_LSB_2										0x72
#define SSD1803A_FS1_CONTRAST_LSB_3										0x73
#define SSD1803A_FS1_CONTRAST_LSB_4										0x74
#define SSD1803A_FS1_CONTRAST_LSB_5										0x75
#define SSD1803A_FS1_CONTRAST_LSB_6										0x76
#define SSD1803A_FS1_CONTRAST_LSB_7										0x77
#define SSD1803A_FS1_CONTRAST_LSB_8										0x78
#define SSD1803A_FS1_CONTRAST_LSB_9										0x79
#define SSD1803A_FS1_CONTRAST_LSB_10									0x7A
#define SSD1803A_FS1_CONTRAST_LSB_11									0x7B
#define SSD1803A_FS1_CONTRAST_LSB_12									0x7C
#define SSD1803A_FS1_CONTRAST_LSB_13									0x7D
#define SSD1803A_FS1_CONTRAST_LSB_14									0x7E
#define SSD1803A_FS1_CONTRAST_LSB_15									0x7F
// Extension Register RE = 1 & IS = 0.
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH0					0x10
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH1					0x11
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0					0x12
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1					0x13
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH0					0x14
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH1					0x15
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH0					0x16
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1					0x17
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH0					0x18
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH1					0x19
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH0					0x1A
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1					0x1B
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH0					0x1C
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH1					0x1D
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH0					0x1E
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1					0x1F
// Extension Register RE = 1 & IS = 1.
#define SSD1803A_FS3_NOSHIFT											0x10
#define SSD1803A_FS3_SHIFT_LINE_1										0x11
#define SSD1803A_FS3_SHIFT_LINE_2										0x12
#define SSD1803A_FS3_SHIFT_LINE_12										0x13
#define SSD1803A_FS3_SHIFT_LINE_3										0x14
#define SSD1803A_FS3_SHIFT_LINE_13										0x15
#define SSD1803A_FS3_SHIFT_LINE_23										0x16
#define SSD1803A_FS3_SHIFT_LINE_123										0x17
#define SSD1803A_FS3_SHIFT_LINE_4										0x18
#define SSD1803A_FS3_SHIFT_LINE_14										0x19
#define SSD1803A_FS3_SHIFT_LINE_24										0x1A
#define SSD1803A_FS3_SHIFT_LINE_124										0x1B
#define SSD1803A_FS3_SHIFT_LINE_34										0x1C
#define SSD1803A_FS3_SHIFT_LINE_134										0x1D
#define SSD1803A_FS3_SHIFT_LINE_234										0x1E
#define SSD1803A_FS3_SHIFT_LINE_1234									0x1F
#define SSD1803A_FS3_NOSCROLL										 	0x10
#define SSD1803A_FS3_SCROLL_LINE_1										0x11
#define SSD1803A_FS3_SCROLL_LINE_2										0x12
#define SSD1803A_FS3_SCROLL_LINE_12										0x13
#define SSD1803A_FS3_SCROLL_LINE_3										0x14
#define SSD1803A_FS3_SCROLL_LINE_13										0x15
#define SSD1803A_FS3_SCROLL_LINE_23										0x16
#define SSD1803A_FS3_SCROLL_LINE_123									0x17
#define SSD1803A_FS3_SCROLL_LINE_4										0x18
#define SSD1803A_FS3_SCROLL_LINE_14										0x19
#define SSD1803A_FS3_SCROLL_LINE_24										0x1A
#define SSD1803A_FS3_SCROLL_LINE_124									0x1B
#define SSD1803A_FS3_SCROLL_LINE_34										0x1C
#define SSD1803A_FS3_SCROLL_LINE_134									0x1D
#define SSD1803A_FS3_SCROLL_LINE_234									0x1E
#define SSD1803A_FS3_SCROLL_LINE_1234									0x1F
// Extension Register RE = 0 & IS = x.
#define SSD1803A_FS01_RETURN_HOME										0x02
#define SSD1803A_FS01_DISPLAY_OFF										0x08
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF								0x0C
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_NOBLINK						0x0E
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_BLINK						0x0F
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS0			0x20
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS1			0x21
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS0			0x24
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS1			0x25
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS0			0x28
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS1			0x29
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS0			0x2C
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS1			0x2D
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS0			0x30
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS1			0x31
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS0			0x34
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS1           0x35
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0			0x38
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1			0x39
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0			0x3C
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1			0x3D
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE				0x80
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE				0xA0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE				0xC0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FIRST_LINE					0x8A
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_SECOND_LINE					0xAA
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_THIRD_LINE					0xCA
// Extension Register RE = 1 & IS = x.
#define SSD1803A_FS23_POWER_DOWN_OFF									0x02
#define SSD1803A_FS23_POWER_DOWN_ON										0x03
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW_MIRROR					0x04
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW							0x05
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW						0x06
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW_MIRROR					0x07
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_12LINE	0x08
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE	0x09
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_12LINE		0x0A
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_34LINE		0x0B
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_12LINE	0x0C
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_34LINE	0x0D
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_12LINE		0x0E
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_34LINE		0x0F
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_NORMAL			0x22
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_REVERSE			0x23
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_NORMAL			0x26
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_REVERSE			0x27
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_NORMAL			0x2A
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_REVERSE			0x2B
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_NORMAL			0x2E
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_REVERSE			0x2F
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_NORMAL			0x32
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_REVERSE			0x33
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_NORMAL			0x36
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_REVERSE			0x37
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL			0x3A
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_REVERSE			0x3B
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_NORMAL			0x3E
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_REVERSE			0x3F
#define SSD1803A_FS23_SCROLL_QUANTITY									0x80
#define SSD1803A_FS23_TEMPERATURE_COEFFICIENT							0x76
#define SSD1803A_FS23_ROM_SELECTION_COMMAND								0x72
// Extension Register RE = x & IS = x.
#define SSD1803A_FS0123_CLEAR_DISPLAY									0x01
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT				0x04
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_SHIFT				0x05
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT				0x06
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_SHIFT				0x07
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_005					0x02
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_010					0x04
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_015					0x06
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_020					0x07
#define SSD1803A_FS0123_ROM_SELECTION_A									0x00
#define SSD1803A_FS0123_ROM_SELECTION_B									0x04
#define SSD1803A_FS0123_ROM_SELECTION_C									0x08

// Function prototypes.
void i2c_initializeMaster(void);
uint8_t i2c_read(void);
void i2c_restart(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write(uint8_t u8Data);
void ssd1803a_clearDisplay(uint8_t u8Address);
void ssd1803a_initialize(uint8_t u8Address);
void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data);
void ssd1803a_writeData(uint8_t u8Address, char cData);
void ssd1803a_writeInstruction(uint8_t u8Address, char cData);
void ssd1803a_writeString(uint8_t u8Address, const char * cData);
void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "tronix.io";
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);
	// I2C Port.
	I2C_SDA = 0;
	I2C_SCL = 0;
	I2C_SDA_TRIS = 1;
	I2C_SCL_TRIS = 1;
	// Output for Backlight.
	DOGM204A_BACKLIGHT = 1;
	DOGM204A_BACKLIGHT_TRIS = 0;

	i2c_initializeMaster();
	ssd1803a_initialize(SSD1803A_ADDRESS_78);
	ssd1803a_romSelection(SSD1803A_ADDRESS_78, SSD1803A_FS0123_ROM_SELECTION_A);

	// Write 5x8 Dots Custom Patterns in SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS0_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			ssd1803a_writeData(SSD1803A_ADDRESS_78, custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string0, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE);
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string1, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE);

	// Display Custom Patterns from SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x00);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x01);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x02);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x03);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x04);
	ssd1803a_writeString(SSD1803A_ADDRESS_78, " - ");

	while(1){
		for(pattern=0; pattern<5; pattern++){
		ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE + 0x08);
			ssd1803a_writeData(SSD1803A_ADDRESS_78, pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void i2c_initializeMaster(void)
{
	// I2C - Master.
	SSPSTAT = 0x80;
	SSPCON1 = 0x28;
	SSPCON2 = 0x00;
	// SSPADD = 0x03 ~400kHz @8MHz.
	// SSPADD = 0x12 ~100kHz @8MHz.
	SSPADD = 0x12;
}

void i2c_restart(void)
{
	SSPCON2bits.RSEN = 1;
	while(SSPCON2bits.RSEN);
}

void i2c_start(void)
{
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
}

void i2c_stop(void)
{
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
}

void i2c_write(uint8_t u8Data)
{
	PIR1bits.SSPIF = 0;
	SSPBUF = u8Data;
	while(!PIR1bits.SSPIF);
	while(SSPCON2bits.ACKSTAT);
}

void ssd1803a_clearDisplay(uint8_t u8Address)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS0123_CLEAR_DISPLAY);
	__delay_ms(2);
}

void ssd1803a_initialize(uint8_t u8Address)
{
	__delay_ms(20);

	i2c_start();
	i2c_write(SSD1803A_ADDRESS_78);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_COMMAND);
	i2c_write(SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	i2c_write(SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE);
	i2c_write(SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW);
	i2c_write(SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00);
	i2c_write(SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1);
	i2c_write(SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6);
	i2c_write(SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3);
	i2c_write(SSD1803A_FS1_CONTRAST_LSB_10);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
	i2c_write(SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF);
	i2c_write(SSD1803A_FS0123_CLEAR_DISPLAY);
	i2c_stop();
	__delay_ms(2);
}

void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_ROM_SELECTION_COMMAND);
	ssd1803a_writeData(u8Address, u8Data);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0);
}

void ssd1803a_writeData(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_DATA);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeInstruction(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeString(uint8_t u8Address, const char * cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(u8Data);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

5.String & Custom Patterns - 4 Lines - I2C, Controlled Backlight.

// Configuration register.
#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.

// TODO - RESET 1-50ms - 0-200us - 1.

// TODO - DEMO MODE - Ajouter des variables
// bottom / top view.
// ROM A / B / C.
// 4lines
// 1 Double Line, 2 Lines.
// 1 Line, 1 Double Line, 1 Line.
// 2 Lines, 1 Double Line.
// 2 Double Line.

// LCD EA-DOGS104-A 4x10 - SSD1803A - 4 Lines - I2C.
// String & Custom Patterns.
// Controlled Backlight.

// Expansion Module - EA-DOGS104-A - Rev.C.

// JP1 - SCL Close.
// JP2 - SDA Close.
// JP3 - VEE Not use.
// JP4 - BCKL Not use.

// Expansion Module.
// SA0 - 0x78 Close.

// Definitions.
// I2C Port.
#define I2C_SCL															LATCbits.LATC3
#define I2C_SDA															LATCbits.LATC4
#define I2C_SCL_TRIS													TRISCbits.TRISC3
#define I2C_SDA_TRIS													TRISCbits.TRISC4
// I2C.
#define I2C_WRITE														0x00
#define I2C_READ														0x01
// Backlight.
#define DOGM204A_BACKLIGHT												LATBbits.LATB0
#define DOGM204A_BACKLIGHT_TRIS											TRISBbits.TRISB0
// SSD1803A Address Select Bit A0.
#define SSD1803A_ADDRESS_78												0x78
#define SSD1803A_ADDRESS_7A												0x7A
#define SSD1803A_CONTROL_CONTINUOUS_COMMAND								0x00
#define SSD1803A_CONTROL_CONTINUOUS_DATA								0x40
#define SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND							0x80
#define SSD1803A_CONTROL_NO_CONTINUOUS_DATA								0xC0
// Extension Register RE = 0 & IS = 0.
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_LEFT							0x10
#define SSD1803A_FS0_DISPLAY_CURSOR_SHIFT_RIGHT							0x14
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_LEFT							0x18
#define SSD1803A_FS0_DISPLAY_SCREEN_SHIFT_RIGHT							0x1C
#define SSD1803A_FS0_SET_CGRAM_ADDRESS									0x40
// Extension Register RE = 0 & IS = 1.
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F00						0x10
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F10_F01						0x11
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F00						0x12
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F20_F11_F01						0x13
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F00						0x14
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F10_F01						0x15
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F00						0x16
#define SSD1803A_FS1_INTERNAL_OSC_BS00_F21_F11_F01						0x17
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F00						0x18
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F10_F01						0x19
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F00						0x1A
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F20_F11_F01						0x1B
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F00						0x1C
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F10_F01						0x1D
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00						0x1E
#define SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F01						0x1F
#define SSD1803A_FS1_SET_SEGRAM_ADDRESS									0x40
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_0							0x50
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_1							0x51
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_2							0x52
#define SSD1803A_FS1_ION0_BON0_CONTRAST_MSB_3							0x53
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_0							0x54
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_1							0x55
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_2							0x56
#define SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3							0x57
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_0 							0x58
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_1							0x59
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_2							0x5A
#define SSD1803A_FS1_ION1_BON0_CONTRAST_MSB_3							0x5B
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_0							0x5C
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_1							0x5D
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_2							0x5E
#define SSD1803A_FS1_ION1_BON1_CONTRAST_MSB_3							0x5F
#define SSD1803A_FS1_FOLLOWER_CONTROL_OFF								0x60
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_0							0x68
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_1							0x69
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_2							0x6A
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_3							0x6B
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_4							0x6C
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_5							0x6D
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6							0x6E
#define SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_7							0x6F
#define SSD1803A_FS1_CONTRAST_LSB_0										0x70
#define SSD1803A_FS1_CONTRAST_LSB_1										0x71
#define SSD1803A_FS1_CONTRAST_LSB_2										0x72
#define SSD1803A_FS1_CONTRAST_LSB_3										0x73
#define SSD1803A_FS1_CONTRAST_LSB_4										0x74
#define SSD1803A_FS1_CONTRAST_LSB_5										0x75
#define SSD1803A_FS1_CONTRAST_LSB_6										0x76
#define SSD1803A_FS1_CONTRAST_LSB_7										0x77
#define SSD1803A_FS1_CONTRAST_LSB_8										0x78
#define SSD1803A_FS1_CONTRAST_LSB_9										0x79
#define SSD1803A_FS1_CONTRAST_LSB_10									0x7A
#define SSD1803A_FS1_CONTRAST_LSB_11									0x7B
#define SSD1803A_FS1_CONTRAST_LSB_12									0x7C
#define SSD1803A_FS1_CONTRAST_LSB_13									0x7D
#define SSD1803A_FS1_CONTRAST_LSB_14									0x7E
#define SSD1803A_FS1_CONTRAST_LSB_15									0x7F
// Extension Register RE = 1 & IS = 0.
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH0					0x10
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS10_DH1					0x11
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0					0x12
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH1					0x13
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH0					0x14
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS10_DH1					0x15
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH0					0x16
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD11_BS11_DH1					0x17
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH0					0x18
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS10_DH1					0x19
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH0					0x1A
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD10_BS11_DH1					0x1B
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH0					0x1C
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS10_DH1					0x1D
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH0					0x1E
#define SSD1803A_FS2_DOUBLE_HEIGHT_UD21_UD11_BS11_DH1					0x1F
// Extension Register RE = 1 & IS = 1.
#define SSD1803A_FS3_NOSHIFT											0x10
#define SSD1803A_FS3_SHIFT_LINE_1										0x11
#define SSD1803A_FS3_SHIFT_LINE_2										0x12
#define SSD1803A_FS3_SHIFT_LINE_12										0x13
#define SSD1803A_FS3_SHIFT_LINE_3										0x14
#define SSD1803A_FS3_SHIFT_LINE_13										0x15
#define SSD1803A_FS3_SHIFT_LINE_23										0x16
#define SSD1803A_FS3_SHIFT_LINE_123										0x17
#define SSD1803A_FS3_SHIFT_LINE_4										0x18
#define SSD1803A_FS3_SHIFT_LINE_14										0x19
#define SSD1803A_FS3_SHIFT_LINE_24										0x1A
#define SSD1803A_FS3_SHIFT_LINE_124										0x1B
#define SSD1803A_FS3_SHIFT_LINE_34										0x1C
#define SSD1803A_FS3_SHIFT_LINE_134										0x1D
#define SSD1803A_FS3_SHIFT_LINE_234										0x1E
#define SSD1803A_FS3_SHIFT_LINE_1234									0x1F
#define SSD1803A_FS3_NOSCROLL										 	0x10
#define SSD1803A_FS3_SCROLL_LINE_1										0x11
#define SSD1803A_FS3_SCROLL_LINE_2										0x12
#define SSD1803A_FS3_SCROLL_LINE_12										0x13
#define SSD1803A_FS3_SCROLL_LINE_3										0x14
#define SSD1803A_FS3_SCROLL_LINE_13										0x15
#define SSD1803A_FS3_SCROLL_LINE_23										0x16
#define SSD1803A_FS3_SCROLL_LINE_123									0x17
#define SSD1803A_FS3_SCROLL_LINE_4										0x18
#define SSD1803A_FS3_SCROLL_LINE_14										0x19
#define SSD1803A_FS3_SCROLL_LINE_24										0x1A
#define SSD1803A_FS3_SCROLL_LINE_124									0x1B
#define SSD1803A_FS3_SCROLL_LINE_34										0x1C
#define SSD1803A_FS3_SCROLL_LINE_134									0x1D
#define SSD1803A_FS3_SCROLL_LINE_234									0x1E
#define SSD1803A_FS3_SCROLL_LINE_1234									0x1F
// Extension Register RE = 0 & IS = x.
#define SSD1803A_FS01_RETURN_HOME										0x02
#define SSD1803A_FS01_DISPLAY_OFF										0x08
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF								0x0C
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_NOBLINK						0x0E
#define SSD1803A_FS01_DISPLAY_ON_CURSOR_ON_BLINK						0x0F
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS0			0x20
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT0_RE0_IS1			0x21
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS0			0x24
#define SSD1803A_FS01_FUNCION_SET_4BIT_13LINE_DHFONT1_RE0_IS1			0x25
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS0			0x28
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT0_RE0_IS1			0x29
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS0			0x2C
#define SSD1803A_FS01_FUNCION_SET_4BIT_24LINE_DHFONT1_RE0_IS1			0x2D
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS0			0x30
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT0_RE0_IS1			0x31
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS0			0x34
#define SSD1803A_FS01_FUNCION_SET_8BIT_13LINE_DHFONT1_RE0_IS1           0x35
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0			0x38
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1			0x39
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS0			0x3C
#define SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT1_RE0_IS1			0x3D
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE				0x80
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE				0xA0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_THIRD_LINE				0xC0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FOURTH_LINE				0xE0
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FIRST_LINE					0x8A
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_SECOND_LINE					0xAA
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_THIRD_LINE					0xCA
#define SSD1803A_FS01_SET_DDRAM_ADDRESS_TOP_FOURTH_LINE					0xEA
// Extension Register RE = 1 & IS = x.
#define SSD1803A_FS23_POWER_DOWN_OFF									0x02
#define SSD1803A_FS23_POWER_DOWN_ON										0x03
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW_MIRROR					0x04
#define SSD1803A_FS23_ENTRY_MODE_SET_TOP_VIEW							0x05
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW						0x06
#define SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW_MIRROR					0x07
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_12LINE	0x08
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE	0x09
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_12LINE		0x0A
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_INVERTING_34LINE		0x0B
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_12LINE	0x0C
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_NOINVERTING_34LINE	0x0D
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_12LINE		0x0E
#define SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT6_INVERTING_34LINE		0x0F
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_NORMAL			0x22
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE0_RE1_REVERSE			0x23
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_NORMAL			0x26
#define SSD1803A_FS23_FUNCION_SET_4BIT_13LINE_BE1_RE1_REVERSE			0x27
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_NORMAL			0x2A
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE0_RE1_REVERSE			0x2B
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_NORMAL			0x2E
#define SSD1803A_FS23_FUNCION_SET_4BIT_24LINE_BE1_RE1_REVERSE			0x2F
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_NORMAL			0x32
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE0_RE1_REVERSE			0x33
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_NORMAL			0x36
#define SSD1803A_FS23_FUNCION_SET_8BIT_13LINE_BE1_RE1_REVERSE			0x37
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL			0x3A
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_REVERSE			0x3B
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_NORMAL			0x3E
#define SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE1_RE1_REVERSE			0x3F
#define SSD1803A_FS23_SCROLL_QUANTITY									0x80
#define SSD1803A_FS23_TEMPERATURE_COEFFICIENT							0x76
#define SSD1803A_FS23_ROM_SELECTION_COMMAND								0x72
// Extension Register RE = x & IS = x.
#define SSD1803A_FS0123_CLEAR_DISPLAY									0x01
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_NOSHIFT				0x04
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_DECREMENT_SHIFT				0x05
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_NOSHIFT				0x06
#define SSD1803A_FS0123_ENTRY_MODE_DDRAM_INCREMENT_SHIFT				0x07
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_005					0x02
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_010					0x04
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_015					0x06
#define SSD1803A_FS0123_TEMPERATURE_COEFFICIENT_SET_020					0x07
#define SSD1803A_FS0123_ROM_SELECTION_A									0x00
#define SSD1803A_FS0123_ROM_SELECTION_B									0x04
#define SSD1803A_FS0123_ROM_SELECTION_C									0x08

// Function prototypes.
void i2c_initializeMaster(void);
uint8_t i2c_read(void);
void i2c_restart(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write(uint8_t u8Data);
void ssd1803a_clearDisplay(uint8_t u8Address);
void ssd1803a_initialize(uint8_t u8Address);
void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data);
void ssd1803a_writeData(uint8_t u8Address, char cData);
void ssd1803a_writeInstruction(uint8_t u8Address, char cData);
void ssd1803a_writeString(uint8_t u8Address, const char * cData);
void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "tronix.io";
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);
	// I2C Port.
	I2C_SDA = 0;
	I2C_SCL = 0;
	I2C_SDA_TRIS = 1;
	I2C_SCL_TRIS = 1;
	// Output for Backlight.
	DOGM204A_BACKLIGHT = 1;
	DOGM204A_BACKLIGHT_TRIS = 0;

	i2c_initializeMaster();
	ssd1803a_initialize(SSD1803A_ADDRESS_78);
	ssd1803a_romSelection(SSD1803A_ADDRESS_78, SSD1803A_FS0123_ROM_SELECTION_A);

	// Write 5x8 Dots Custom Patterns in SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS0_SET_CGRAM_ADDRESS);
	uint8_t line = 0;
	uint8_t pattern = 0;
	for(pattern=0; pattern<5; pattern++){
		for(line=0; line<8; line++){
			ssd1803a_writeData(SSD1803A_ADDRESS_78, custom_patterns[pattern][line]);
		}
	}
	
	// Display String.
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string0, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FIRST_LINE);
	ssd1803a_writeStringSetCursor(SSD1803A_ADDRESS_78, string1, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_SECOND_LINE);

	// Display Custom Patterns from SSD1803A CGRAM.
	ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FOURTH_LINE);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x00);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x01);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x02);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x03);
	ssd1803a_writeData(SSD1803A_ADDRESS_78, 0x04);
	ssd1803a_writeString(SSD1803A_ADDRESS_78, " - ");

	while(1){
		for(pattern=0; pattern<5; pattern++){
		ssd1803a_writeInstruction(SSD1803A_ADDRESS_78, SSD1803A_FS01_SET_DDRAM_ADDRESS_BOTTOM_FOURTH_LINE + 0x08);
			ssd1803a_writeData(SSD1803A_ADDRESS_78, pattern);
			__delay_ms(800);
		}
	}
	return(0);
}

// Functions.
void i2c_initializeMaster(void)
{
	// I2C - Master.
	SSPSTAT = 0x80;
	SSPCON1 = 0x28;
	SSPCON2 = 0x00;
	// SSPADD = 0x03 ~400kHz @8MHz.
	// SSPADD = 0x12 ~100kHz @8MHz.
	SSPADD = 0x12;
}

void i2c_restart(void)
{
	SSPCON2bits.RSEN = 1;
	while(SSPCON2bits.RSEN);
}

void i2c_start(void)
{
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
}

void i2c_stop(void)
{
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
}

void i2c_write(uint8_t u8Data)
{
	PIR1bits.SSPIF = 0;
	SSPBUF = u8Data;
	while(!PIR1bits.SSPIF);
	while(SSPCON2bits.ACKSTAT);
}

void ssd1803a_clearDisplay(uint8_t u8Address)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS0123_CLEAR_DISPLAY);
	__delay_ms(2);
}

void ssd1803a_initialize(uint8_t u8Address)
{
	__delay_ms(20);

	i2c_start();
	i2c_write(SSD1803A_ADDRESS_78);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_COMMAND);
	i2c_write(SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	i2c_write(SSD1803A_FS23_EXTENDED_FUNCTION_SET_FONT5_NOINVERTING_34LINE);
	i2c_write(SSD1803A_FS23_ENTRY_MODE_SET_BOTTOM_VIEW);
	i2c_write(SSD1803A_FS1_INTERNAL_OSC_BS01_F21_F11_F00);
	i2c_write(SSD1803A_FS2_DOUBLE_HEIGHT_UD20_UD10_BS11_DH0);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS1);
	i2c_write(SSD1803A_FS1_FOLLOWER_CONTROL_ON_RAB_6);
	i2c_write(SSD1803A_FS1_ION0_BON1_CONTRAST_MSB_3);
	i2c_write(SSD1803A_FS1_CONTRAST_LSB_10);
	i2c_write(SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0);
	i2c_write(SSD1803A_FS01_DISPLAY_ON_CURSOR_OFF);
	i2c_write(SSD1803A_FS0123_CLEAR_DISPLAY);
	i2c_stop();
	__delay_ms(2);
}

void ssd1803a_romSelection(uint8_t u8Address, uint8_t u8Data)
{
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_FUNCION_SET_8BIT_24LINE_BE0_RE1_NORMAL);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS23_ROM_SELECTION_COMMAND);
	ssd1803a_writeData(u8Address, u8Data);
	ssd1803a_writeInstruction(u8Address, SSD1803A_FS01_FUNCION_SET_8BIT_24LINE_DHFONT0_RE0_IS0);
}

void ssd1803a_writeData(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_DATA);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeInstruction(uint8_t u8Address, char cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(cData);
	i2c_stop();
}

void ssd1803a_writeString(uint8_t u8Address, const char * cData)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

void ssd1803a_writeStringSetCursor(uint8_t u8Address, const char * cData, uint8_t u8Data)
{
	i2c_start();
	i2c_write((uint8_t)(u8Address | I2C_WRITE));
	i2c_write(SSD1803A_CONTROL_NO_CONTINUOUS_COMMAND);
	i2c_write(u8Data);
	i2c_write(SSD1803A_CONTROL_CONTINUOUS_DATA);
	while(*cData != '\0')
		i2c_write(*cData++);
	i2c_stop();
}

08.2018