/* PIC LCD HITACHI 44780 */

// This waveform will write an ASCII Byte out to the LCD's screen. The ASCII code to be displayed is eight bits long and is sent to the
// LCD either  four or eight bits at a time. If four bit mode is used, two "nybbles" of data (Sent high four bits and then low four bits
// with "E" Clock pulse with each nybble) are sent to make up a full eight bit transfer. The "E" Clock is used to initiate the data
// transfer within the LCD. 
// Sending parallel data as either four or eight bits are the two primary modes of operation. While there are secondary considerations 
// and modes, deciding how to send the data to the LCD is most critical decision to be made for an LCD interface application. 
// Eight bit mode is best used when speed is required in an application and at least ten I/O pins are available. Four bit mode requires a
// minimum of six bits. To wire a microcontroller to an LCD in four bit mode, just the top four bits (DB4-7) are written to. 
// The "R/S" bit is used to select whether data or an instruction is being transferred between the microcontroller and the LCD. If the
// Bit is set, then the byte at the current LCD "Cursor" Position can be read or written. When the Bit is reset, either an instruction is
// being sent to the LCD or the execution status of the last instruction is read back (whether or not it has completed).
#define pic18f4455 1
#include "pic18fregs.h"

// Porta B dati LCD
#define LCD_TRIS	TRISB
#define LCD_PORT	PORTB
// RA0 - Register Select
// RA1 - Read/Write LCD
// RA2 - Clock
#define LCD_RS   PORTAbits.RA0
#define LCD_TRIS_RS  TRISAbits.TRISA0
#define LCD_RW   PORTAbits.RA1
#define LCD_TRIS_RW  TRISAbits.TRISA1
#define LCD_EN  PORTAbits.RA2
#define LCD_TRIS_CK  TRISAbits.TRISA2

// Define initialization commands
// 8-bit-interface, 2-lines
#define LCD_MODE 0x38
#define LCD_ON 0x0F
#define LCD_CURSOR 0x06
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02

code char at __CONFIG1H conf1 = 0xFB; // Select HS OSC
code char at __CONFIG4L conf2 = 0x81; // Disable LVP
code char at __CONFIG2H conf3 = 0x0E; // Disable WDT
code char at __CONFIG3H conf4 = 0x85; // Disable A/D on PORTB


void delay(long ms) {
	long i;
	while (ms--) {
		for (i=0; i < 330; i++) {
			Nop();	
		}
	}
}

void sendcmd(char dato) {
	LCD_RS = 0;
	LCD_EN = 0;
	delay(1);
	LCD_EN = 1;
	delay(1);
	LCD_PORT = dato;
	delay(1);
}

void sendchar(char dato) {
	LCD_RS = 1;
	LCD_EN = 0;
	delay(1);
	LCD_EN = 1;
	delay(1);
	LCD_PORT = dato;
	delay(1);
	LCD_EN = 0;
}

void initlcd() {
	delay(20);
	sendcmd(LCD_MODE);
	sendcmd(LCD_MODE);
	sendcmd(LCD_ON);
	sendcmd(LCD_CLEAR);
	sendcmd(LCD_CURSOR);
	sendcmd(0x80);
	sendcmd(LCD_HOME);
}

void main() {
	char dato=0x10;
	// set pin to output
	LCD_TRIS = 0;
	LCD_TRIS_RS = 0;
	LCD_TRIS_RW = 0;
	LCD_TRIS_CK = 0;
	ADCON1 = 0x1F; // make sure PORTA is in digital mode (table on page 250 in manual)
	LCD_PORT = 0;
	LCD_RS = 0;
	LCD_RW = 0;
	LCD_EN = 0;
	// Now initialize LCD
	initlcd();
	// Start sending chars...
	while(1) {
		sendchar(dato);
		delay(5);
		dato++;
	}
}

