!! Harmony Custom Name of GPIO, no space !!
---------------------------------------------------------------------
SSD1306_RS       (PA12 as GPIO output, Latch Hight)
SSD1306_RESET    (PA27 as GPIO output, Latch Hight)

---------------------------------------------------------------------
=====================================================================
---------------------------------------------------------------------
!! Add below code in app_drv_spi1.h !!
---------------------------------------------------------------------
    // APP_DRV_SPI1_STATE_SERVICE_TASKS,
    APP_DRV_SPI1_STATE_SPLASH,
    APP_DRV_SPI1_STATE_SPLASH_WAIT_COMPLETE,
    APP_DRV_SPI1_STATE_UPDATE,
    APP_DRV_SPI1_STATE_ERROR,
    APP_DRV_SPI1_STATE_IDLE,

---------------------------------------------------------------------


---------------------------------------------------------------------
!! Add below code in app_drv_spi1.c !!
---------------------------------------------------------------------
    switch ( app_drv_spi1Data.state )
    {
    case APP_DRV_SPI1_STATE_INIT:
        app_drv_spi1Data.state = APP_DRV_SPI1_STATE_SPLASH;
        break;

    case APP_DRV_SPI1_STATE_SPLASH:
        app_drv_spi1Data.state = APP_DRV_SPI1_STATE_SPLASH_WAIT_COMPLETE;
        break;

    case APP_DRV_SPI1_STATE_SPLASH_WAIT_COMPLETE:
        app_drv_spi1Data.state = APP_DRV_SPI1_STATE_UPDATE;
        break;

    case APP_DRV_SPI1_STATE_UPDATE:
        break;

    case APP_DRV_SPI1_STATE_ERROR:
        app_drv_spi1Data.state = APP_DRV_SPI1_STATE_IDLE;
        break;

    case APP_DRV_SPI1_STATE_IDLE:
        break;
    }

---------------------------------------------------------------------
#include "app_drv_usart1.h"
#include "driver/spi/drv_spi.h"
#include "system/time/sys_time.h"
#include "peripheral/port/plib_port.h"
#include "Alphabet_Fonts.h"
#include "Microchip_Logo.h"
#include <stdio.h>
#include <string.h>

---------------------------------------------------------------------
#define LCM_WIDTH 128
#define LCM_HEIGHT 64
int  LogoX=126;
const uint8_t LCM_InitCMD[] = {
    0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40, 0x8D, 0x14, 0x20, 0x02, 0xA1,
    0xC8, 0xDA, 0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6, 0xAF
};
enum {
    LCM_BUS_CMD = 0,
    LCM_BUS_DAT
};

DRV_HANDLE SPI1Handle;
SYS_TIME_HANDLE SplashTimerHandle;

---------------------------------------------------------------------
void LCM_BusWrite( int bus, void *bytes, size_t counts )
{
    DRV_SPI_TRANSFER_HANDLE SPI1WriteHandle;

    if     ( bus==LCM_BUS_CMD ) SSD1306_RS_Clear();
    else if( bus==LCM_BUS_DAT ) SSD1306_RS_Set();

    DRV_SPI_WriteTransferAdd( SPI1Handle, bytes, counts, &SPI1WriteHandle );
    while( DRV_SPI_TransferStatusGet(SPI1WriteHandle)!=DRV_SPI_TRANSFER_EVENT_COMPLETE );
}

void LCM_SetCursor( uint8_t x, uint8_t y )
{
    uint8_t OUT[3] = { 0x0F & x, 0x10 + (x >> 4), 0xB0 + y };

    LCM_BusWrite( LCM_BUS_CMD, (void*)OUT, 3 );
}

void LCM_DrawBitmap( uint8_t sx, uint8_t sy, uint8_t width, uint8_t height, const unsigned char *byte )
{
    for( int y=0; y<(height/8); y++ )
    {
        LCM_SetCursor( sx, sy+y );
        LCM_BusWrite( LCM_BUS_DAT, (void*)byte, width-sx );
        byte+=width;
    }
}

---------------------------------------------------------------------
        SSD1306_RESET_Clear();
        SPI1Handle = DRV_SPI_Open(DRV_SPI_INDEX_0, DRV_IO_INTENT_WRITE);
        if(SPI1Handle == DRV_HANDLE_INVALID)
        {
            app_drv_spi1Data.state = APP_DRV_SPI1_STATE_ERROR;
            break;
        }
        SSD1306_RESET_Set();

        DRV_SPI_TRANSFER_SETUP  SPI1Setup;
        SPI1Setup.baudRateInHz  = 1000000;
        SPI1Setup.clockPhase    = DRV_SPI_CLOCK_PHASE_VALID_LEADING_EDGE;
        SPI1Setup.clockPolarity = DRV_SPI_CLOCK_POLARITY_IDLE_LOW;
        SPI1Setup.dataBits      = DRV_SPI_DATA_BITS_8;
        SPI1Setup.chipSelect    = (SYS_PORT_PIN)SYS_PORT_PIN_NONE;
        SPI1Setup.csPolarity    = DRV_SPI_CS_POLARITY_ACTIVE_LOW;
        DRV_SPI_TransferSetup(SPI1Handle, &SPI1Setup);

        LCM_BusWrite( LCM_BUS_CMD, (void*)LCM_InitCMD, sizeof(LCM_InitCMD) );

---------------------------------------------------------------------
        USART1printf("DRV_SPI1 error!\r\n");

---------------------------------------------------------------------
        LCM_DrawBitmap( LogoX, 0, LCM_WIDTH, LCM_HEIGHT, Microchip_Logo );
        LogoX = LogoX-2;
        if( LogoX<0 )
        {
            SYS_TIME_DelayMS(1000, &SplashTimerHandle);
            app_drv_spi1Data.state = APP_DRV_SPI1_STATE_SPLASH_WAIT_COMPLETE;
        }

---------------------------------------------------------------------
        if( SYS_TIME_DelayIsComplete(SplashTimerHandle) == true )
        {
            app_drv_spi1Data.state = APP_DRV_SPI1_STATE_UPDATE;
        }

=====================================================================


---------------------------------------------------------------------
#define FONT_WIDTH  7
#define FONT_HEIGHT 8
char  OutString[20];
char  LCM_Usart1Rx;
char  LCM_Usart2Rx;
float LCM_I2c1Temp;
char  LCM_I2c1EERPOM;
int   LCM_I2c2Accel[3];
char  Alphabet[95] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&()[]{}_\\|;:,.`'\"<>+-*/=? ";

---------------------------------------------------------------------
void LCM_Clear( void )
{
    unsigned char LCM_Blank[1024];
    memset(LCM_Blank, 0, 1024);
    LCM_DrawBitmap(0, 0, LCM_WIDTH, LCM_HEIGHT, LCM_Blank);	
}

void LCM_DrawFont( uint8_t sx, uint8_t row, char ch )
{
    int chIdx = 0;

    while( ch != Alphabet[chIdx] ) { chIdx++; }	
    LCM_SetCursor(sx, row);
    LCM_BusWrite( LCM_BUS_DAT, (void*)(Alphabet_Fonts+(chIdx*FONT_WIDTH)), FONT_WIDTH );
}

void LCM_DrawString( uint8_t sx, uint8_t row, char *str )
{
    for( int x=0 ; x<strlen(str); x++ )
    {
        LCM_DrawFont( sx+(x*FONT_WIDTH), row, str[x] );
    }
}

---------------------------------------------------------------------
        LCM_Clear();

---------------------------------------------------------------------
            LCM_Clear();

---------------------------------------------------------------------
        sprintf( OutString, "LCM: Hello World" );
        LCM_DrawString(0, 0, OutString);
        sprintf( OutString, "USART1 RX: %c", LCM_Usart1Rx );
        LCM_DrawString(0, 1, OutString);
        sprintf( OutString, "USART2 RX: %c", LCM_Usart2Rx );
        LCM_DrawString(0, 2, OutString);
        sprintf( OutString, "I2C1 Temp: %2.1f'C", LCM_I2c1Temp );
        LCM_DrawString(0, 3, OutString);
        sprintf( OutString, "I2C1 EEPROM: 0x%02X", LCM_I2c1EERPOM );
        LCM_DrawString(0, 4, OutString);
        sprintf( OutString, "I2C2 AccelX: %5d", LCM_I2c2Accel[0] );
        LCM_DrawString(0, 5, OutString);
        sprintf( OutString, "I2C2 AccelY: %5d", LCM_I2c2Accel[1] );
        LCM_DrawString(0, 6, OutString);
        sprintf( OutString, "I2C2 AccelZ: %5d", LCM_I2c2Accel[2] );
        LCM_DrawString(0, 7, OutString);

=====================================================================


---------------------------------------------------------------------
!! Add below code in app_drv_spi1.h !!
---------------------------------------------------------------------
extern char  LCM_Usart1Rx;
extern char  LCM_Usart2Rx;
extern float LCM_I2c1Temp;
extern char  LCM_I2c1EERPOM;
extern int   LCM_I2c2Accel[3];

=====================================================================


---------------------------------------------------------------------
!! Add below code in app_drv_usart1.c !!
---------------------------------------------------------------------
#include "app_drv_spi1.h"

---------------------------------------------------------------------
            LCM_Usart1Rx = Uart1ReadBuf[0];

=====================================================================


---------------------------------------------------------------------
!! Add below code in app_drv_usart2.c !!
---------------------------------------------------------------------
#include "app_drv_spi1.h"

---------------------------------------------------------------------
            LCM_Usart2Rx = Uart2ReadBuf[0];

=====================================================================


---------------------------------------------------------------------
!! Add below code in app_drv_i2c1.c !!
---------------------------------------------------------------------
#include "app_drv_spi1.h"

---------------------------------------------------------------------
            LCM_I2c1Temp = (float)((I2C1ReadBuf_9800[0]<<4)| (I2C1ReadBuf_9800[1]>>4))/16.0f;

---------------------------------------------------------------------
            LCM_I2c1EERPOM = I2C1ReadBuf_24AA[0];

=====================================================================


---------------------------------------------------------------------
!! Add below code in app_drv_i2c2.c !!
---------------------------------------------------------------------
#include "app_drv_spi1.h"

---------------------------------------------------------------------
                LCM_I2c2Accel[0] = (short)(AxisOutByte[1]<<8|AxisOutByte[0]);
                LCM_I2c2Accel[1] = (short)(AxisOutByte[3]<<8|AxisOutByte[3]);
                LCM_I2c2Accel[2] = (short)(AxisOutByte[5]<<8|AxisOutByte[4]);

=====================================================================


---------------------------------------------------------------------
!! Modify below code in app_drv_i2c1.c !!
---------------------------------------------------------------------
            // USART1printf("Temp = %2.1f\r",
            //              (float)((I2C1ReadBuf_9800[0]<<4)|(I2C1ReadBuf_9800[1]>>4))/16.0f);

---------------------------------------------------------------------
            // USART1printf("\t\tEEPROM = 0x%X\r", I2C1ReadBuf_24AA[0]);

=====================================================================


---------------------------------------------------------------------
!! Modify below code in app_drv_i2c2.c !!
---------------------------------------------------------------------
                // USART1printf("\t\t\t\tG-Sensor = (%5d, %5d, %5d)\r",
                //                (short)(AxisOutByte[1]<<8|AxisOutByte[0]),
                //                (short)(AxisOutByte[3]<<8|AxisOutByte[2]),
                //                (short)(AxisOutByte[5]<<8|AxisOutByte[4]));

---------------------------------------------------------------------
- If you have implemented Advanced Exercise : MPLAB Data Visualizer -
---------------------------------------------------------------------
                // unsigned char DVBuf[8] = { 0x03,
                //                            AxisOutByte[0], AxisOutByte[1],
                //                            AxisOutByte[2], AxisOutByte[3],
                //                            AxisOutByte[4], AxisOutByte[5],
                // USART2write( DVBuf, 8 );

=====================================================================
