#include <msp430.h>
#include "stdint.h"

/* LCD port és vezérlő bitek megadása */
#define LCD_PORT     P2OUT
#define LCD_PORT_DIR P2DIR
#define LCD_MASK     BIT7+BIT6+BIT5+BIT4
//#define LCD_RS       P2OUT_bit.P6
//#define LCD_RS_DIR   P2DIR_bit.P6
#define LCD_RS_BIT	BIT0
//#define LCD_E         P2OUT_bit.P7
#define LCD_E_BIT	BIT1
//#define LCD_E_DIR    P2DIR_bit.P7

/**-----------------------------------------------
* Inline függvény, amely egy regiszter valamelyik
* bitcsoportját atomi művelettel módosítja
*-----------------------------------------------
* param reg a módosítandó regiszter neve
* param val a beírandó érték (helyiérték-helyesen!)
* param mask a módosítandó bitcsoportot kijelölő maszk
*/

#define ChangeBits(reg,val,mask) reg^=((reg^val)&mask)

/**----------------------------------------------
*   Késleltető eljárás (1 - 65535 ms)
*-----------------------------------------------
* param delay a késleltetés ms egységben megadva
*/
void delay_ms(uint16_t delay) {
         uint16_t i;
         for(i=0; i<delay; i++) {
           __delay_cycles(1000);
         }
}

/**----------------------------------------------
*   LCD Enable bemenet pulzálása
*-----------------------------------------------
*/
void lcd_toggle_E() {
//         LCD_E = 1;
         LCD_PORT|=LCD_E_BIT;
           __delay_cycles(100); //500
//         LCD_E = 0;
           LCD_PORT&=~LCD_E_BIT;
           __delay_cycles(100); //500
}

/**----------------------------------------------
        *   Egy bájt kiküldése az LCD vezérlőjének
        *-----------------------------------------------
        * param val a kiírandó érték
        * param cmd regiszterválasztó bit (0: parancs, 1: adat)
        */

void lcd_write(uint8_t val, uint8_t cmd) {
		 if (cmd) {
			 LCD_PORT|=LCD_RS_BIT;
		 }
		 else {
			 LCD_PORT&=~LCD_RS_BIT;
		 }

//         LCD_RS = cmd;
         ChangeBits(LCD_PORT,(val&0xF0),LCD_MASK);
//P1OUT^=((P1OUT^(val&0xF0))&LCD_MASK);
//         P1OUT=P1OUT^((P1OUT^(val&0xF0))&LCD_MASK);
         lcd_toggle_E();
         ChangeBits(LCD_PORT,((val&0x0F)<<4),LCD_MASK);
         lcd_toggle_E();
         __delay_cycles(1000);
}
/*-----------------------------------------------
*   LCD kijelző inicializálása
*-----------------------------------------------
*/

void lcd_init (void){
//-- Az LCD port inicializálása
         ChangeBits(LCD_PORT,0x00,LCD_MASK);
         ChangeBits(LCD_PORT_DIR,LCD_MASK,LCD_MASK);
         P2SEL = 0;
//         LCD_RS = 0;
         LCD_PORT&=~LCD_RS_BIT;
//         LCD_RS_DIR = 1;
         LCD_PORT_DIR|=LCD_RS_BIT;
//         LCD_E = 0;
         LCD_PORT&=~LCD_E_BIT;
//         LCD_E_DIR = 1;
         LCD_PORT_DIR|=LCD_E_BIT;
         delay_ms(100);                      //40ms várakozás bekapcsolás után

//-- Az LCD vezérlőjének inicializálása:
//-- 1. szoftveres LCD reset: 0x30 (8-bites mód) kiírása háromszor
//-- 2. 4-bites üzemmód beállítása
//-- 3. Képernyőtörlés, kurzor kikapcsolása
         ChangeBits(LCD_PORT,0x30,LCD_MASK);
         lcd_toggle_E ();
         delay_ms(5);                        //várjunk legalább 4.1ms-ot
         lcd_toggle_E ();
         __delay_cycles(100);                //várjunk legalább 100us-ot
         lcd_toggle_E ();
         __delay_cycles(40);                 //várjunk legalább 37us-ot
         ChangeBits(LCD_PORT,0x20,LCD_MASK); //0x20 = 4-bites üzemmód
         lcd_toggle_E ();
         delay_ms(5);                        //várjunk legalább 4.1ms-ot

//-- Innen kezdve minden bájtot két félbájtként kell kiírni! ------
         lcd_write(0x28,0);                  // display mód beállítás
         delay_ms(5);                        //várjunk legalább 4.1ms-ot
         lcd_write(0x08,0);                  // display letiltás
         lcd_write(0x01,0);                  // képernyőtörlés
         lcd_write(0x0C,0);                  // display be, cursor, és villogás ki
}

/**----------------------------------------------
*  Karakterfüzér kiírása az LCD-re
*-----------------------------------------------
* param p_str karakterfüzér mutató (nullával lezárt stringre mutat)
*/
void lcd_puts(char* p_str) {
         char c;
         while ((c=*p_str)) {
             lcd_write(c,1);
        	 //lcd_putc(c);
             p_str++;
         }
}

/**----------------------------------------------
*  Karakter kiírása az LCD-re az ékezetes
*  karakterek kódjának áttranszformálásával
*-----------------------------------------------
* param data a kiírandó karakter ANSI kódja
*/
void lcd_putc(unsigned char data) {
         char c;
         if (c=data) {
 //          switch(c) {
        	 //            case 'á':  c = 0x00; break;
        	 //             case 'é':  c = 0x01; break;
        	 //             case 'í':  c = 0x02; break;
        	 //             case 'ó':  c = 0x03; break;
        	 //             case 'ú':  c = 0x04; break;
        	 //case 'ü':  c = 0x05; break;
        	 //case 'ű':  c = 0x06; break;
        	 //case 'ő':  c = 0x07; break;
        	 //case 'ö':  c = 0xEF; break;
           //}
        	 if (c=='a') { c=0x00; }
           lcd_write(c,1);
         }
}
