/* PICCOLO project
 * Copyright (c) 2009 Istvan Cserny (cserny@atomki.hu)
 *
 */

#include "piccolo_all.h"
#include  <stdio.h>  
#include <delays.h>

/** \file
Az ipari szabványnak tekinthető párhuzamos illesztővel ellátott 2x16 karakateres 
LCD kijelző használatát mutatja be, 4 bites módban, printf használattal. 


Hardver igény:
   - PICCOLO projekt alapkapcsolás PIC18F14K50 vagy PIC18F4550 mikrovezérlővel,
     esetleg a Microchip Low Pin Count USB vagy a PICDEM Full Speed USB demókártya
   - 2x16 karakteres LCD kijelző

*/

// hardverfüggő részletek elkülönítése
#define RSHIGH         LEDport |= 0x01;
#define RSLOW          LEDport &= 0xFE;
#define RWHIGH         LEDport |= 0x02;
#define RWLOW          LEDport &= 0xFD;
#define EHIGH          LEDport |= 0x04;
#define ELOW           LEDport &= 0xFB;
#if defined(__18F14K50)
   #define BUSY_FLAG PORTCbits.RC7;
#elif  defined(__18F4550)
   #define BUSY_FLAG PORTDbits.RD7;
#endif 
#define DATA_DIR_RD    LEDtris = 0xF0;
#define DATA_DIR_WR    LEDtris = 0x00;
#define OUTPUT_DATA(x) {LEDport = (LEDport & 0x0F) | x;}



//prototypes
void epulse (void);
void lcd_write(
     unsigned char cmd, unsigned char data_flag, unsigned char chk_busy, unsigned char dflag);
void lcd_init(void);
void putch (char c);
 
void epulse(void){
  Delay10TCYx(2);  EHIGH;  Delay10TCYx(2); ELOW; Delay10TCYx(2);
}

void lcd_write(
     unsigned char cmd, unsigned char data_flag, unsigned char chk_busy, unsigned char dflag){
  char bflag,c;
  if (chk_busy) {
    RSLOW;       //RS = 0 to check busy
    // check busy
    DATA_DIR_RD;  //set data pins all inputs
    RWHIGH;       // R/W = 1, for read
    do {
      EHIGH; Delay10TCYx(2);  // upper 4 bits
      bflag = BUSY_FLAG; 
      ELOW; Delay10TCYx(2);
      epulse();
    } while(bflag);
  } else {
    Delay10KTCYx(12); // don't use busy, just delay
  }
  DATA_DIR_WR;
  if (data_flag)  { RSHIGH;}   // RS=1, data byte
  else    RSLOW;   // RS=0, command byte
  // device is not busy
  RWLOW;       // R/W = 0, for write
  c = cmd & 0xF0;  // send upper 4 bits
  OUTPUT_DATA(c);
  epulse();
  if (dflag) {
    c = (cmd & 0x0F)<<4;  //send lower 4 bits
    OUTPUT_DATA(c);
    epulse();
  }
}
    

void lcd_init(void) {

stdout = _H_USER;          // assign STDOUT to our single char output function
                             // which will be character output to LCD


  Delay10KTCYx(60);  //wait for device to settle
  lcd_write(0x20,0,0,0);  // 4 bit interface
  lcd_write(0x28,0,0,1);  // 2 line display, 5x7 font
  lcd_write(0x28,0,0,1);  // repeat
  lcd_write(0x06,0,0,1);  // enable display
  lcd_write(0x0C,0,0,1);  // turn display on; cursor, blink is off
  lcd_write(0x01,0,0,1);  // clear display, move cursor to home
  Delay1KTCYx(36);   // wait for busy flag to be ready
}

// send 8 bit char to LCD
void putch(char c) {
    lcd_write(c,1,1,1);
}

#if defined(__18CXX)
void _user_putc (auto char c) {   //char function called by _H_USER stream
    putch(c);
}
#endif

void main(void){
  // configure, see control pins as outputs 
  // initialize as low
  DATA_DIR_WR;
  ELOW; RSLOW;  RWLOW; 
  lcd_init ();
printf("0123456789ABCDEFGHIJKLMNOPQSRTUVXYZ");
lcd_write(0xC0,0,1,1);  // cursor to 2nd line
printf("-----:*+!@abcdefghijklmnopqrstuvxyz");
  while(1) {
      // shift left
      lcd_write(0x18,0,1,1);  
      Delay10KTCYx(120);
      Delay10KTCYx(120);
      Delay10KTCYx(120);
  }
}
