/****************************************************************************
LCDC2.C

Code snippet to drive a standard LCD using 4-bit mode (data D4-D7).

***************************************************************************/
 .
 .
 .
// The six bus pins are defined here.
// this example happens to use PIC port B3, B4, B5, B6 for LCD data
// and port B5 for LCD ENABLE and port B6 for LCD RS.
#define LCD_D4          PIN_B1
#define LCD_D5          PIN_B2
#define LCD_D6          PIN_B3
#define LCD_D7          PIN_B4
#define LCD_EN          PIN_B5
#define LCD_RS          PIN_B6
 .
 .
 .
 .
 .
 .
// misc display defines
#define LINE_1          0x00
#define LINE_2          0x40
#define CLEAR_DISP      0x01

// prototype statements
#separate void LCD_Init ( void );
#separate void LCD_SetPosition ( unsigned int cX );
#separate void LCD_PutChar ( unsigned int cX );
#separate void LCD_PutCmd ( unsigned int cX );
#separate void LCD_PulseEnable ( void );
#separate void LCD_SetData ( unsigned int cX );

// whatever pins you assign to the display 
// MUST be in a bus that is a CCS type "standard_io".
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
 .
 .
 .
 .
 .
 .
// code start here
void main ( void )
    {
    char cX;

    cX = 1;                                           // set number
    LCD_Init();                                       // set up LCD for 4-wire bus, etc.
    LCD_PutCmd ( CLEAR_DISP );                        // clear screen
    LCD_SetPosition ( LINE_1 + 0 );                   // set line and offset on line
    printf ( LCD_PutChar, "Test #%u", cX );           // display message
    LCD_SetPosition ( LINE_2 + 5 );                   // set line and offset on line
    printf ( LCD_PutChar, "2nd test" );               // display message

    while ( 1 );                                      // stop
    }
 .
 .
 .
 .
 .
 .
/* SIX LCD-SPECIFIC FUNCTIONS ARE BELOW============================== */

#separate void LCD_Init ( void )
    {
    LCD_SetData ( 0x00 );
    delay_ms ( 200 );       /* wait enough time after Vdd rise */
    output_low ( LCD_RS );
    LCD_SetData ( 0x03 );   /* init with specific nibbles to start 4-bit mode */
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_SetData ( 0x02 );   /* set 4-bit interface */
    LCD_PulseEnable();      /* send dual nibbles hereafter, MSN first */
    LCD_PutCmd ( 0x2C );    /* function set (all lines, 5x7 characters) */
    LCD_PutCmd ( 0x0C );    /* display ON, cursor off, no blink */
    LCD_PutCmd ( 0x01 );    /* clear display */
    LCD_PutCmd ( 0x06 );    /* entry mode set, increment & scroll left */
    }

#separate void LCD_SetPosition ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) | 0x08 );
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );
    LCD_PulseEnable();
    }

#separate void LCD_PutChar ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    if ( !cSkip )
        {
        output_high ( LCD_RS );
        LCD_SetData ( swap ( cX ) );     /* send high nibble */
        LCD_PulseEnable();
        LCD_SetData ( swap ( cX ) );     /* send low nibble */
        LCD_PulseEnable();
        output_low ( LCD_RS );
        }
    }

#separate void LCD_PutCmd ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    }

#separate void LCD_PulseEnable ( void )
    {
    output_high ( LCD_EN );
    delay_us ( 3 );         // was 10
    output_low ( LCD_EN );
    delay_ms ( 3 );         // was 5
    }

#separate void LCD_SetData ( unsigned int cX )
    {
    output_bit ( LCD_D4, cX & 0x01 );
    output_bit ( LCD_D5, cX & 0x02 );
    output_bit ( LCD_D6, cX & 0x04 );
    output_bit ( LCD_D7, cX & 0x08 );
    }