/**********************************************************
 es23C.c - Termometro con display LCD I2C
 *********************************************************
 Legge la temperatura da MCP9700 e invia a un modulo LCD a
 caratteri 2x8 con connessione I2C.
 I2C con MSSP (RC1:0).
 Comando per backlight negativo (0=on - 1=off) con RC4 ad
 alta corrente, open drain.
 *********************************************************
 PIC16F1615 (16F1619)
 *********************************************************/
/* I/O
 PORTA
 | RA5 | RA4 | RA3 | RA2 | RA1 | RA0 |
 |-----|-----|-----|-----|-----|-----|
 |  -  |  -  | MCLR| 9700| CLK | DAT |

 PORTC
 | RC5 | RC4 | RC3 | RC2 | RC1 | RC0 |
 |-----|-----|-----|-----|-----|-----|
 |  -  | BKL |  -  |  -  | SDA | SCL |

 oscillatore interno 4MHz
*********************************************************/
#include <xc.h>
#include "i2cLCD.c"

#define _XTAL_FREQ 4000000   // Fosc 4MHz
#define I2C_clk 100000       // I2C clock 100kHz

/*************************************************************
 Costanti LCD
************************************************************/
// LCD i2c address
//#define addr 0x78      // SA1=SA0=0 selez. hardware
//#define add 0X7A;    // SA1=0 SA0=1
//#define add 0X7C;    // SA1=1 SA0=0
//#define add 0X7E;    // SA1=SA0=1

/*************************************************************
						CONFIG
************************************************************/
// CONFIG1
#pragma config FEXTOSC=OFF, RSTOSC=HFINT1, CLKOUTEN=OFF 
#pragma config CSWEN=ON, FCMEN=ON, MCLRE=ON, PWRTE=OFF  
#pragma config WDTE=OFF, LPBOREN=OFF, BOREN=ON       
#pragma config BORV=LOW, PPS1WAY=ON, STVREN=ON  
#pragma config WRT=OFF, LVP=ON, CP=OFF, CPD=OFF 


void out9700(int mcp9700);

// ************************************************ ********
void main() {
    int mcp9700 = 0;        // valore letto da 9700
	
 // set oscillatore interno per 4MHz
    OSCFRQ  = 0b00000110;   //HFOSC 16MHz
    OSCCON1 = 0b01100010;   //HFINT1 1/4
	
	
    i2c_Init(); 		    // Inizializza I2C
    LCD_Init(); 			// Inizializza LCD

 // Setup pin ingresso analogico
    ANSA2 = 1; 		     	// ANA2(RA2) analogico
	WPUA2=0;                // no wpu
	TRISA2=1;               // input
 // Setup ADC e FVR	
    ADCON1 = 0b10010011; 	// giust. a destra, AD Fosc/8
 // ADCON1 = 0b11010011;    // Fosc/16 
	ADACT = 0;  			// no trigger					 
    ADCON0 = 0b00001001; 	// ANA2(RA2), ADC ON
    FVRCON = 0b10000001; 	// riferimento interno 1.024V

    LATAbits.LATA4 = 0;     // backlight on
    
// Lettura temperatura
    LCD_ROMstr("MCP9700");  // nella prima riga
    while(1){
      mcp9700 = 0;
      for(char i=0;i<16;i++){ // 16 letture 
	    __delay_ms(5);        // attesa prima della nuova conversione
	    GO = 1; 			  // avvia conversione
	    while(GO);		      // wait completamento conversione
	    mcp9700 += (ADRES-500); // sottrai offset
      }
      mcp9700 /= 16;          // media delle letture
      LCD_posyx(1,1);      	  // riga 2
      out9700(mcp9700); 	  // scrivi temperatura
      __delay_ms(1000);       // aggiornamento ogni secondo
    }
}

// visualizza la temperatura
// Stringa per visualizzare °C
char str3[3] = {0xDF, 'C', '\0'};
void out9700(int mcp9700){   // Visualizza temperatura
  char digit;
  if(mcp9700 < 0){           // se negativo
    LCD_ROMstr("-");         // visualizza il segno -
    mcp9700 = abs(mcp9700);  // valore assoluto
  } else LCD_ROMstr(" ");    // se positivo, spazio
  
  digit = mcp9700 / 100;       // cifra decine
  if(digit==0)LCD_ROMstr(" "); // sopprime se 0
    else LCD_dat(digit + '0'); // converte  e visualizza
  digit = (mcp9700 - digit * 100) / 10; // cifra unità 
  LCD_dat(digit + '0');        // converte e visualizza
  LCD_ROMstr(".");             // punto decimale
  digit = mcp9700 % 10;        // parte decimale 
  LCD_dat(digit+'0');          // converte visualizza
  LCD_ROMstr(str3);            // °C celsius
}