LCDmodule.c

code format="c" /* LCD module */


 * 1) include 
 * 2) include 
 * 3) include "define.h"

/* LCD display lines */
 * 1) define L0_p1	 0x80		   /** Line 0 (upper line) with positions 1 to 16 */
 * 2) define L0_p2	 0x81
 * 3) define L0_p3	 0x82
 * 4) define L0_p4	 0x83
 * 5) define L0_p5	 0x84
 * 6) define L0_p6	 0x85
 * 7) define L0_p7	 0x86
 * 8) define L0_p8	 0x87
 * 9) define L0_p9	 0x88
 * 10) define L0_p10  0x89
 * 11) define L0_p11  0x8A
 * 12) define L0_p12  0x8B
 * 13) define L0_p13  0x8C
 * 14) define L0_p14  0x8D
 * 15) define L0_p15  0x8E
 * 16) define L0_p16  0x8F


 * 1) define L1_p1	 0xC0		  /** Line 1 (bottom line) with positions 1 to 16 */
 * 2) define L1_p2	 0xC1
 * 3) define L1_p3	 0xC2
 * 4) define L1_p4	 0xC3
 * 5) define L1_p5	 0xC4
 * 6) define L1_p6	 0xC5
 * 7) define L1_p7	 0xC6
 * 8) define L1_p8	 0xC7
 * 9) define L1_p9	 0xC8
 * 10) define L1_p10	 0xC9
 * 11) define L1_p11	 0xCA
 * 12) define L1_p12	 0xCB
 * 13) define L1_p13	 0xCC
 * 14) define L1_p14	 0xCD
 * 15) define L1_p15	 0xCE
 * 16) define L1_p16	 0xCF

/* Register selection and Read/Write inputs */
 * 1) define READ 	1                          /** Read Operation */
 * 2) define WRITE	0                          /** Write Operation */
 * 3) define INSTR	0                          /** Instruction register is selected */
 * 4) define DATA	1                          /** Data Register is selected */

/* LCD settings */
 * 1) define FUNCTION_SET   0x38                /** 8 bit bus, 2 lines */
 * 2) define DISPLAY_OFF    0x08                /** Display control BitD is low. Entire display is turned off. Bit3 set*/
 * 3) define DISPLAY_ON     0x0F	            /** Display control BitD is high. Entire display is turned on. Bit3 set. Cursor control bit and blink bit are set to high(turned on)*/
 * 4) define CLEAR_DISPLAY  0x01                /** Clear all the display data. Bit0 set */
 * 5) define ENTRY_MODE     0x06                /** Increment mode, Entire display Shift off, Bit2 set */

/* PSP pins */
 * 1) define LCD_DATA	PORTD                  /** LCD 8 data bits */
 * 2) define LCD_D_DIR	TRISD                  /** PORTD Data direction register. Setting a TRISD bit(=1) will make the corresponding PORTD pin an input, while clearing it (=0) will make the pin an output */
 * 3) define LCD_RS		PORTEbits.RE0          /** LCD Register Select control line */
 * 4) define	LCD_RS_DIR	TRISEbits.TRISE0	   /** Register Select Direction Control bit. 1=Input, 0=Output.*/
 * 5) define LCD_RW		PORTEbits.RE1          /** LCD Read/Write control line */
 * 6) define	LCD_RW_DIR	TRISEbits.TRISE1	   /** Read/Write Direction Control bit. 1=Input, 0=Output.*/
 * 7) define LCD_E		PORTEbits.RE2          /** LCD Enable control line */
 * 8) define	LCD_E_DIR	TRISEbits.TRISE2       /** Enable Direction Control bit. 1=Input, 0=Output.*/

/* Variables */ char LCDBuffer[O_BUFSIZE];                 /** Output buffer */ unsigned char writeIndex = 0;              /** Write Index for buffer */ unsigned char readIndex = 0;               /** Read Index for buffer */ unsigned char LCDWantsToSend = FALSE;      /** Flag indicating data to be sent */

/* Prototypes */ void initialise_LCD (void); void Instruction_LCD(unsigned char value); void BF_LCD(void); unsigned char get_DDRAM (void); void putchar_LCD (unsigned char cval); void send_LCD (unsigned char dispval); void string_LCD(unsigned char *pointer); void sendNext(void); unsigned char isBusy(void);

/**
 * Function that initialises the LCD by instruction to an 8-bit interface mode.
 * @pre LCD has power.

void initialise_LCD (void) {	TRISE = 0x00;                           /* Configuration for output on PORTD and PORTE */ TRISD = 0x00; ADCON1 = 0b00000110;                    /* The A/D port configuration bits PCFG2:PCFG0 (ADCON1<2:0>) SET,to configure pins RE2:RE0 as digital I/O */ PORTD = 0x00; LCD_E_DIR = 0; LCD_RS_DIR = 0; LCD_RW_DIR = 0;

/* Initialisation using delays.h */

Delay1KTCYx(120);                       /* Power on delay of 30ms */ Instruction_LCD(FUNCTION_SET);          /* 8 bit interface, 2-lines */ Delay10TCYx(16);                        /* Delay of 39 microseconds */ Instruction_LCD(DISPLAY_ON);            /* display, cursor and blink on */ Delay10TCYx(16);                        /* Delay of 39 microseconds */ Instruction_LCD(CLEAR_DISPLAY);         /* Clear the display and return cursor home */ Delay100TCYx(62);                       /* Delay of 1.53 ms */ Instruction_LCD(ENTRY_MODE);            /* Entry Mode Sets: cursor moves to the righ and display appears stationary */ } /**
 * Function that sends an instruction to the LCD.
 * @param value The command character to send
 * @pre LCD has been initialised

void Instruction_LCD(unsigned char value) { BF_LCD;                                /* check through Busy Flag that the LCD is ready to go */ LCD_RS = INSTR;                         /* selects Instruction register (IR) */ LCD_RW = WRITE;                         /* Sets write mode */ LCD_E = 1;	                          /* Enable signal */ LCD_DATA = value;	                      /* send out the command */ Nop; LCD_E = 0; 	                          /* external write cycle is complete */ }

/**
 * Function that detects the LCD Busy Flag(BF)before executing the next instrunction.
 * @pre The LCD must be initalised.
 * @post The LCD is not busy.

void BF_LCD(void) { 	char check_bf = 1; LCD_D_DIR = 0xFF;                  /* configure LCD data bus for input */ LCD_RS = INSTR; 	               /* Set LCD for instruction mode (IR) */ LCD_RW = READ; 	                   /* Set to read busy flag */ while (check_bf) {		LCD_E = 1; 	                   /* Enable signal */ check_bf = LCD_DATA;           /* Read busy flag + DDram address */ LCD_E 	= 0; 	               /* complete a read cycle */ check_bf = check_bf & 0x80;    /* check Busy Flag, Busy = 1. DBit7 used for Busy Flag output */ }	LCD_D_DIR 	= 0x00;                /* configure LCD data bus for output */ }

/**
 * Function that reads the DDRAM value.
 * @return The DDRAM data bits 0-6
 * @pre The LCD must be initalised.

unsigned char get_DDRAM (void) {	char temp; LCD_D_DIR = 0xFF;                 /* configure LCD data port for input */ LCD_RS = INSTR;			          /* select IR register */ LCD_RW = READ;			          /* setup to read busy flag */ LCD_E = 1; 			              /* LCD E-line to high */ temp = LCD_DATA & 0x7F;           /* read DDRAM address and set busy flag to low */

LCD_E = 0; 			              /* LCD E-line to low */ return temp; }

/**
 * Function that sends character to send_LCD. It toggles the data between the top and bottom display lines of the LCD.
 * The 'end of line' symbol sets the data to display in the bottom row, whilst the 'carriage return' symbol sets it back to the top one.
 * @param cval The character to be sent.
 * @pre LCD is fully initialised

void putchar_LCD (unsigned char cval) {   BF_LCD; 	                                         /* Wait for LCD to be ready */ if(cval == '\n')	                                /* Line feed means set to row 2 */ {	 	Instruction_LCD(L1_p1); 		                /* set cursor to column 1 row 2 */ return; }	if(cval == '\r')	                                /* Carriage return means set to row 1 */ {		Instruction_LCD(L0_p1);		                    /* set cursor to column 1 row 1 */ return; }   send_LCD(cval); }

/**
 * Function that transmits a character to LCD.
 * @param dispval The character to be sent.
 * @pre The LCD must not be busy and it must be initialised.
 * @post The LCD busy flag is set until it finishes

void send_LCD (unsigned char dispval) {	LCD_RS = DATA;                /* Set LCD in data mode */ LCD_RW = WRITE;               /* Set LCD in write mode */ LCD_E = 1;                    /* LCD E-line High */ LCD_DATA = dispval;           /* Send data to LCD */ LCD_E = 0;                    /* LCD E-line to Low */ }

/** * Stores a string in the LCDbuffer to be sent to the LCD. * Notes: Calling this method to rapidly with too much data will cause * the buffer to overflow, and data may not be transmitted properly. * @param pointer The unsigned char* pointing to the string. * @pre The LCD is properly initialised * @post The string is added to the LCDbuffer */

void string_LCD(unsigned char* pointer) {	while (*pointer != '\0') {

LCDBuffer[writeIndex] = *pointer; writeIndex ++; if(writeIndex == O_BUFSIZE)	       /* End of circular buffer */ {			writeIndex = 0;			       /* Loop round */ }		pointer++;					       /* Next char */ }	LCDWantsToSend = TRUE; }

/** * Sends the next character stored in the LCDBuffer. * @pre The LCD is not busy. Important to check this first. * @post The character is sent, and the buffer moves along. If there are no more characters to send in the buffer, then LCDWantsToSend will be * set to FALSE. */

void sendNext(void) {	if(!LCDWantsToSend) return;	        /* If there's nothing to send, don't. */ putchar_LCD(LCDBuffer[readIndex]); readIndex++; if(readIndex == O_BUFSIZE)	        /* End of circular buffer */ {		readIndex = 0;			        /* Loop round */ }	if(readIndex == writeIndex)	        /* If the read catches up with the write */ {		LCDWantsToSend = FALSE; } }

/** * Gets whether or not the LCD is busy * @return boolean An unsigned char of 0 or !0 (specifically 0x80) */

unsigned char isBusy(void) {	char check_bf = 1; LCD_D_DIR = 0xFF;                  /* configure LCD data bus for input */ LCD_RS = INSTR; 	               /* Set LCD for instruction mode (IR) */ LCD_RW = READ; 	                   /* Set to read busy flag */ LCD_E = 1; 	                       /* Enable signal */ check_bf = LCD_DATA;               /* Read busy flag + DDram address */ LCD_E 	= 0; 	                   /* complete a read cycle */ check_bf = check_bf & 0x80;        /* check Busy Flag, Busy = 1. DBit7 used for Busy Flag output */ LCD_D_DIR = 0x00;                  /* configure LCD data bus for output */ return check_bf;	               /* check_bf = 0 or 0x80 */ } code