#include <kd_sfrs.h>
#include <lcd.h>
#include <string.h>

#define LCD_INS	0xfe
#define LCD_DAT 0x01
#define LCD_ENA	0x04

#define LCD_LINEA2 0xC0
#define LCD_LINEA1 0x80
#define LCD_CLRSCR 0x01			/* RETARD DE 1.64 ms */
 

// Las variables con los valores correctos, listos para ser mostrados en pantalla
signed int tem_disp;
unsigned int hum_disp;
unsigned int vel_disp;
unsigned int dir_disp;

void WRITE_LCD_4BITS();

void INICIALITZA_LCD()
{
/*
;0      X000 0000B = 00H   ->              IOPORT1
;1      X000 0001B = 01H
;15     X000 1111B = 0FH
*/ 

  DELAY_10mS();
  DELAY_10mS();

  wsr=0;
  ioport1=0x30 & LCD_INS;
  WRITE_LCD_4BITS();
  DELAY_10mS();

  wsr=0;
  ioport1=0x30 & LCD_INS;
  WRITE_LCD_4BITS();
  DELAY_10mS();

  wsr=0;
  ioport1=0x30 & LCD_INS;
  WRITE_LCD_4BITS();
  DELAY_10mS();

  wsr=0;
  ioport1=0x20 & LCD_INS; /* interface de 4 bits */
  WRITE_LCD_4BITS();
  DELAY_10mS();

/*AHORA YA PODEMOS USAR LA FUNCION DE INSTRUCION LCD*/
/*FUNCTION SET- 4 bits dades, 2 lines, caracter font*/

  INSTRUCCIO_LCD(0x28);

  /*DISPLAY ON/OFF-DISPLAY ON, CURSOR OFF, CURSOR NO BLINK*/
  INSTRUCCIO_LCD(0x0C);

  INSTRUCCIO_LCD(0x06);  /*ENTRY MODE SET-INCREMENT CURSOR, CURSOR MOVEMENT*/

  INSTRUCCIO_LCD(0x01);  /*CLEAR DISPLAY*/
  DELAY_10mS();                     
  /*ESTE RETARDO DEBERIA DE SER DE 1.64mS*/
}

void WRITE_LCD_4BITS()
{
/*AQUESTA FUNCIO ES NOMES PER US INTERN DE LA LLIBRERIA DEL DISPLAY*/

  asm{NOP;NOP;}
  wsr=0;
  ioport1 = ioport1 ^ LCD_ENA; /*XORB IOPORT1,#LCD_ENA*/

  asm{  
  NOP;NOP;NOP;NOP;NOP;
  NOP;NOP;NOP;NOP;NOP;
  }

  wsr=0;
  ioport1 = ioport1 ^ LCD_ENA; /*XORB IOPORT1,#LCD_ENA*/
  asm{NOP;}
}  


void INSTRUCCIO_LCD(unsigned char inst)
{ 
  wsr=0;
  ioport1=0xF0 & inst & LCD_INS ;                 /* RS=0 */
  WRITE_LCD_4BITS();
  inst<<=4;
  asm{
  NOP;NOP;
  NOP;NOP;NOP;
  }
  wsr=0;
  ioport1 =0xF0 & inst & LCD_INS;
  WRITE_LCD_4BITS();
  DELAY_40uS();
}

void DADA_LCD(unsigned char dato)
{  
  wsr=0;
  ioport1=0xF0 & dato; /*parte alta primero*/
  ioport1=ioport1|LCD_DAT;   /*RS=1*/
  WRITE_LCD_4BITS();
  dato<<=4;
  asm{
  NOP;NOP;
  NOP;NOP;NOP;
  }
  wsr=0;
  ioport1=0x0F0 & dato;
  ioport1=ioport1|LCD_DAT;
  WRITE_LCD_4BITS();
  DELAY_40uS();
}

void CLRSCR_LCD()
{
  INSTRUCCIO_LCD(LCD_CLRSCR);
  DELAY_10mS();
}

void DELAY_10mS()
{
  unsigned int TIMER_LCD;

  TIMER_LCD=2000;
  while(TIMER_LCD!=0)
  {
     TIMER_LCD--;
  }
}  

void DELAY_40uS()
{
  unsigned int TIMER_LCD;

  TIMER_LCD=40;
  while(TIMER_LCD!=0)
  {
   TIMER_LCD--;
  }
}

void GOTOXY(unsigned char x, unsigned char y)
/*   1<=x<=16  ,  1<=Y<=2 */
{
   unsigned char gotopos;
   gotopos=0x80 | ((y-1)*0x40) | (x-1);
   INSTRUCCIO_LCD(gotopos);
}

void show_value_lcd(unsigned int wValor, int lon, char rell, int x, int y) 
{
      
	  unsigned char xifra;
	  unsigned int valor;
	  int i=0;
	  valor=wValor;
	  while (valor > 0 || wValor==0) {
		GOTOXY(x-i,y);
		xifra=valor%10+'0';
		valor=valor/10;
		DADA_LCD(xifra);
		wValor=1; //para no volver a entrar en el bucle
		i++;
	  }

	  while (i<lon) {
		GOTOXY(x-i,y);
		DADA_LCD(rell);
		i++;
	  }
}

void show_char_lcd(unsigned int wValor, int x, int y) 
{

		GOTOXY(x,y);
		DADA_LCD(wValor);
}

void inits_lcd()
{
	INICIALITZA_LCD();
 	CLRSCR_LCD();
}

void show_msg_lcd(char missatge[], int x, int y)
{
	unsigned int i=0;
	
	GOTOXY(x,y);
	
	while (i<strlen(missatge)) {
		DADA_LCD(missatge[i]);
		i++;
	}
}



/**Funciones para mostrar valores de los modos**/

void mostrar_tem()
{
	signed int tem_abs;
	char signo;
	tem_abs=tem_disp;

	// La temperatura puede ser negativa
	if (tem_abs<0) {
		signo='-'; // '-'
		tem_abs=-tem_abs;
	} else {
	       	// El ' ' sobreescribirá al '-' si pasamos de tem. negativa a positiva
		signo=' '; // ' '
	}
		
	show_msg_lcd("temperatura",1,1);
	show_char_lcd(signo,12,1);
	show_value_lcd(tem_abs,2,' ',14,1);
	show_char_lcd('C',16,1);
	show_char_lcd(0xDF,15,1);
}

void visual_tem() 
{
	signed int i=-2;
	signed int conv=(tem_disp)/10;

	GOTOXY(1,2);
	while(i<0) {	  
	  DADA_LCD((conv<=i)?0xDB:' ' );
	  i++;
	}
	while(i<5) {	  
	  DADA_LCD( (conv>=i)?0xFF:' ' );
	  i++;
	}


}

void mostrar_hum()
{
	show_msg_lcd("humedad",1,1);
	show_value_lcd(hum_disp,3,' ',15,1);
	show_char_lcd('%',16,1);
}

void visual_hum() 
{
	int i=0;
	int conv=(7*hum_disp)/100;

	GOTOXY(1,2);
	while(i<conv) {
	  DADA_LCD(0xFF);
	  i++;
	}

	while(i<7) {
	  DADA_LCD(' ');
	  i++;
	}
	
}

void mostrar_vel()
{
char* velocitats[] = {
 "calm            ",
 "light air       ",
 "light breeze    ",
 "gentle breeze   ",
 "moderate breeze ",
 "fresh breeze    ",
 "strong breeze   ",
 "near gale       ",
 "gale            ",
 "strong gale     ",
 "storm           ",
 "violent storm   ",
 "hurricane       "
};

	unsigned int i;
		
	show_value_lcd(vel_disp,3,' ',3,2);
	show_msg_lcd("km/h",4,2);
	
	// vel_disp en km/h
	i=0;
	if (vel_disp>1) i=1;
	if (vel_disp>6) i=2;
	if (vel_disp>11) i=3;
	if (vel_disp>19) i=4;
	if (vel_disp>29) i=5;
	if (vel_disp>39) i=6;
	if (vel_disp>50) i=7;
	if (vel_disp>61) i=8;
	if (vel_disp>74) i=9;
	if (vel_disp>87) i=10;
	if (vel_disp>101) i=11;
	if (vel_disp>118) i=12;
	
	show_msg_lcd(velocitats[i],1,1);


}

void mostrar_dir()
{
char* direccions[] = {
  "tramunt.",
  "gregal  ",
  "llevant ",
  "xaloc   ",
  "migjorn ",
  "llebeig ",
  "ponent  ",
  "mestral "
};

	signed int i=0;
	
	show_msg_lcd("direccion",1,1);
	show_value_lcd(dir_disp,3,' ',15,1);
        show_char_lcd(0xDF,16,1);

	// Transformación para sacar el índice del vector:
	i=dir_disp+22; // Hacer que 0 grados sea donde empieza el viento norte
	i=i/45;        // Clasificar en uno de los 8 vientos
	i=i%8;         // Para conseguir rango [0-7]
	
	show_msg_lcd(direccions[i],1,2);
	
}