
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar

//________________________________________________________________________________________

// -----> lcd_data del lcd-routines original lo reemplacé por put_char y funcionó <------
//________________________________________________________________________________________ 
 
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
 
// sendet ein Datenbyte an das LCD

//==========
#define length 30
#define ZEILENLAENGE 20
char displayzeile[ZEILENLAENGE];

// hasta aca es del otro
 
void put_char(unsigned char temp1)
{
   unsigned char temp2 = temp1;
 
   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
 
   temp1 = temp1 >> 4;
   temp1 = temp1 & 0x0F;
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp1;               // setzen
   lcd_enable();
 
   temp2 = temp2 & 0x0F;
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp2;               // setzen
   lcd_enable();
   
   _delay_us(62); //estaba 42
}
 
// sendet einen Befehl an das LCD
 
void lcd_command(unsigned char temp1)
{
   unsigned char temp2 = temp1;
 
   LCD_PORT &= ~(1<<LCD_RS);        // RS auf 0 setzen
 
   temp1 = temp1 >> 4;              // oberes Nibble holen
   temp1 = temp1 & 0x0F;            // maskieren
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp1;               // setzen
   lcd_enable();
 
   temp2 = temp2 & 0x0F;            // unteres Nibble holen und maskieren
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp2;               // setzen
   lcd_enable();
   
   _delay_us(62); // estaba 42
}
 
// erzeugt den Enable-Puls
void lcd_enable(void)
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
   // http://www.mikrocontroller.net/topic/81974#685882
   LCD_PORT |= (1<<LCD_EN);
    _delay_us(1);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
   // http://www.mikrocontroller.net/topic/80900
   LCD_PORT &= ~(1<<LCD_EN);
}
 
// Initialisierung: 
// Muss ganz am Anfang des Programms aufgerufen werden.
 
void lcd_init(void)
{
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN);   // Port auf Ausgang schalten
 
   // muss 3mal hintereinander gesendet werden zur Initialisierung
 
   _delay_ms(19); // estaba 15
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x03;            
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
   lcd_enable();
 
   _delay_ms(5);
   lcd_enable();
 
   _delay_ms(1);
   lcd_enable();
   _delay_ms(1);
 
   // 4 Bit Modus aktivieren 
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x02;
   lcd_enable();
   _delay_ms(1);
 
   // 4Bit / 2 Zeilen / 5x7
   lcd_command(0x28); // estaba 0x28->00101000

//http://www.mikrocontroller.net/topic/166979#1596768
//   lcd_command(0b00100100);  // DB5=1: 4-bit-Modus; DB2=1: Extension-Bit
   lcd_command(0b00001001);  // DB3=1 ^ DB0=1 : 4zeilig einschalten

    
   // (0x0C) -- Display ein / Cursor aus / kein Blinken
   lcd_command(0x0C); // 0D->00001101-> Cursor aus / blinkt
 
   // inkrement / kein Scrollen
   lcd_command(0x06); //(0x06)->00000110 ; (0x07)->00000111-Scrollen
 
   lcd_clear();
}
 
// Sendet den Befehl zur Löschung des Displays
 
void lcd_clear(void)
{
   lcd_command(CLEAR_DISPLAY);
   _delay_ms(5);
}
 
// Sendet den Befehl: Cursor Home
 
void lcd_home(void)
{
   lcd_command(CURSOR_HOME);
   _delay_ms(5);
}
 
// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
 
void set_cursor(uint8_t x, uint8_t y)
{
  uint8_t tmp;
 
  switch (y) {
    case 1: tmp=0x80+0x00+x; break;    // 1. Zeile -- set_cursor(0,0);
    case 2: tmp=0x80+0x40+x; break;    // 2. Zeile -- set_cursor(0,2);
    case 3: tmp=0x80+0x10+x; break;    // 3. Zeile -- set_cursor(4,3);
    case 4: tmp=0x80+0x50+x; break;    // 4. Zeile -- set_cursor(4,4);
  }
  lcd_command(tmp);
}
 
// Schreibt einen String auf das LCD
 
void lcd_string(char *data)
{
    while(*data) {
        put_char(*data);
        data++;
    }
}

// ***************desde aca con el otro codigo ****AB HIER FÜR LAUFSCHRIFT***************
//================================================================
// ***************************************************************

/*******************************************************************************
Diese Funktion erzeugt ein delay von lediglich 4 Taktzyklen
Input:  -
Output: -
*******************************************************************************/
static inline void _delayFourCycles(unsigned int __count)
{
    if ( __count == 0 )
        __asm__ __volatile__( "rjmp 1f\n 1:" );    // 2 cycles
    else
        __asm__ __volatile__ (
    	    "1: sbiw %0,1" "\n\t"
    	    "brne 1b"                              // 4 cycles/loop
    	    : "=w" (__count)
    	    : "0" (__count)
    	   );
}
/* Ende der Funktion ---------------------------------------------------------*/


/*******************************************************************************
Diese Definition erzeugt ein delay von wenigen µs. Wichtig hierbei ist, die
richtige Definition der Taktfrequenz mit dem der Controller betrieben wird.
Diese Definition muss in der .h Datei unter [XTAL] eingestellt werden.
Input:  Zahl der µs die als Pause gewünscht ist
Output: -
*******************************************************************************/
#define delay_us(us)  _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )
/* Ende der Funktion ---------------------------------------------------------*/


/*******************************************************************************
Diese Funktion erzeugt ein delay im ms- Bereich.
Input:  Zahl der ms die als Pause gewünscht ist
Output: -
*******************************************************************************/
void delay_ms(unsigned int count)
{
	while (count !=0)
	{
		delay_us(1000);
		count--;
	}
}
/* Ende der Funktion ---------------------------------------------------------*/


/*******************************************************************************
Diese Funktion sendet eine Zeichenkette an das Display
Input:  Den zu übertragenden Text
Output: -
*******************************************************************************/
void put_string(char *text)
{
    while(*text)
    {
    	put_char(*text);
    	text++;
    }
}
/* Ende der Funktion ---------------------------------------------------------*/


/*******************************************************************************
Diese Funktion zählt die Zeichen einer Zeichenkette und gibt sie an den
Funktionsaufruf zurück.
Input:  den zu zählenden Text
Output: die Anzahl der Zeichen in der Zeichenkette
*******************************************************************************/
char strleng(char *text)
{
	char n;

	for (n=0; *text != '\0'; text++)
	{
		n++;
	}
	return n;
}
/* Ende der Funktion ---------------------------------------------------------*/



/*******************************************************************************
Diese Funktion erzeugt eine Pause in der Laufschrift.
So wird die Pausenzeit in der Laufschrift nur an einer Stelle geändert
Input:  -
Output: -
*******************************************************************************/
void laufpause(void)
{
	delay_ms(800); /*---> el laufschrift corre mas rapido o despacio */
}
/* Ende der Funktion ---------------------------------------------------------*/


/*******************************************************************************
Diese Funktion erzeugt eine Laufschrift auf dem Display
Input:  text: den Text der über das Display laufen soll
		zeile: in welcher Zeile der Text laufen soll
Output: -
*******************************************************************************
void laufschrift(char* text, char zeile)
{

	char* ZeigerText= text;			// es wird ein Zeiger auf den übergebenen Text zugewiesen
	char TextLaenge= strleng(text);	// es werden die Anzahl der Zeichen des übergebenen Text ermittelt
	char AktTextPos= 0;				// die aktuelle Position
	char countdown = TextLaenge+ZEILENLAENGE;	//--> ZEILENLAENGE wird in der .h Datei festgelegt

	// die while-Schleife läuft "programmiertechnisch" von unten nach oben da in dieser Schleife
	// if-Schleifen enthalten sind. Würde die Schleife nicht von unten nach oben laufen würde eine
	// beendete Schleife direkt durch die folgende erfolgen. So wie hier (von unten nach oben) wird
	// die folgende if-Anweisung erst im nächsten Durchlauf erfolgen!
	while (countdown != 0)
	{

		// Diese if-Anweisung schiebt den letzten Teil des Lauftextes aus dem Display und füllt
		// den Rest mit Leerzeichen auf
		if(countdown <= ZEILENLAENGE )
		{
			set_cursor( 0, zeile);	// Cursor am Anfang der Zeile positionieren
			AktTextPos+=1;			// Position um eins erhöhen

			// Diese Schleife schreibt die letzten Zeichen des Textes auf das Display wobei
			// es von mal zu mal weniger Zeichen sind
			for(char i=AktTextPos; i < TextLaenge; i++)
			{
				put_char(  *(ZeigerText + i)  );
			}
			put_char(' ');			// Leerzeichen an das Ende anfügen
			laufpause();
			countdown --;
		}

		// Diese If-Anweisung schiebt den Text über das Display bis das Ende des Textes am
		// rechten Displayrand angekommen ist
		if( (countdown <= (TextLaenge) ) && (countdown > ZEILENLAENGE) )
		{
			set_cursor( 0, zeile);	// Cursor am Anfang der Zeile positionieren

			AktTextPos+=1;	// Position um eins erhöhen

			// Diese Schleife schreibt den Text vom linken bis zum rechten Rand des Displays.
			// Es sind immer 16 Zeichen!!
			for(char i=0; i < (ZEILENLAENGE); i++)
			{
				put_char(*(ZeigerText + (AktTextPos + i) ));
			}
			laufpause();
			countdown --;

		}


		// Diese if-Anweisung beginnt den Text von Links nach rechts zu schieben.
		// Dabei beginnt der der Text am rechten Rand und schiebt den Text
		// so lange bis der Text den linken Rand des Displays erreicht hat.
		if(countdown > (TextLaenge) )
		{
			// diese Schleife zählt die Zeilenposition vom rechten Rand runter
			// bis diese schließlich am linken Rand angekommen ist. Die Variable
			// muss "signed" sein da es sonst nicht funktioniert!
			for(signed char i=(ZEILENLAENGE-1); i>= 0; i--)
			{
				set_cursor( i, zeile);	// Der Cursor wird von mal zu mal weiter nach vorne gesetzt
											// (i-1) da das erste Zeichen ja mit 0 anfängt und somit
											// das letzte "Zeilenlaenge - 1" ist

				// Diese Schleife schreibt die Zeichen an die Position. dabei wird von mal zu mal
				// immer ein Zeichen mehr geschrieben. (nicht über den rechten Rand hinaus.
				for(char j=0; j <= (ZEILENLAENGE-i); j++)
				{
					put_char(  *(ZeigerText + j)  );
				}
				laufpause();
				countdown --;
			}
		}
	}// While- ENDE

}*/
/* Ende der Funktion ---------------------------------------------------------*/
