//###########################################################################
// FILE:   blinky_cpu01.c
// TITLE:  LED Blink Example for F2837xS.
//
//! \addtogroup cpu01_example_list
//! <h1> Blinky </h1>
//!
//! This example blinks LED X
//
//###########################################################################
// $TI Release: F2837xS Support Library v180 $
// $Release Date: Fri Nov  6 16:27:58 CST 2015 $
// $Copyright: Copyright (C) 2014-2015 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

	#include "F28x_Project.h"     // Device Headerfile and Examples Include File
    #include <stdlib.h>
	#include <ctype.h>
	#include <stdio.h>


//**************************************************
// LCD constants
// All the following pins must be set as output
//**************************************************

#define LCD_D0 41	//J1 Pin 5
#define LCD_D1 65	//J5 Pin 47
#define LCD_D2 71	//J1 Pin 2
#define LCD_D3 72   //J2 Pin 13
#define LCD_RS 78	//J2 Pin 11
#define LCD_E  90	//J1 Pin 3
#define LCD_RW 89	//J1 Pin 4
#define LCD_LED 43	//J1 Pin 9




//**************************************************
//               Constant Definitions

#define LEFT 0
#define RIGHT 1

#define TURN_ON_LED_LCD 1
#define TURN_OFF_LED_LCD 0

#define TURN_ON_CURSOR 1
#define TURN_OFF_CURSOR 0

#define BLINKING_ON 1
#define BLINKING_OFF 0

//**************************************************


/**
 * This function generates the Enable pulse.
 *
 *
 * @warning This function is a Private one. It should not be used by the user.
 */
void enable_pulse_LCD (void);
#define Epulse enable_pulse_LCD


/**
 * This function generates the Enable pulse.
 *
 *
 * @param bit_0 bit 0 of the data bus (4 bit modality)
 *
 * @param bit_1 bit 1 of the data bus (4 bit modality)
 *
 * @param bit_2 bit 2 of the data bus (4 bit modality)
 *
 * @param bit_3 bit 3 of the data bus (4 bit modality)
 *
 * @warning This function is a Private one. It should not be used by the user.
 */
void send_command_LCD (unsigned char bit_3, unsigned char bit_2, unsigned char bit_1, unsigned char bit_0);
#define SendCommand send_command_LCD


/**
 * This function locates the cursor at home location. First line first character.
 *
 */
void home_LCD(void);
#define HomeLCD home_LCD


/**
 * This function shifts the LCD screen on the left or rigt.
 *
 * @param shift Specify where the shift should be [LEFT, RIGHT].
 *
 * @param number_of_shift Specify the number of times the shift is executed.
 *
 * @note Use the constants LEFT, RIGHT to specify the direction
 *       to ensure the compatibility with LCD_44780_I2C library.
 */
void shift_LCD(unsigned char shift, unsigned char number_of_shift);
#define ShiftLCD shift_LCD


/**
 * This function shifts the LCD cursor on the left or rigt. The position of the cursor is where the
 * next writting will be performed.
 *
 * @param shift Specify where the shift should be [LEFT, RIGHT].
 *
 * @param number_of_shift Specify the number of times the shift is executed.
 *
 * @note Use the constants LEFT, RIGHT to specify the direction
 *       to ensure the compatibility with LCD_44780_I2C library.
 */
void shift_cursor_LCD(unsigned char shift,unsigned char number_of_shift);
#define ShiftCursorLCD shift_cursor_LCD


/**
 * This function locates the LCD cursor on the selected line.
 *
 * @param line Specify the number of the line [1,2,3,4]
 *
 * @warning It might not work with all the LCD Dipslays. Tested on 20x4 16x2 LCD displays.
 */
void goto_line_LCD (unsigned char line);
#define GotoLineLCD goto_line_LCD


/**
 * This function locates the LCD cursor to an arbitrary X Y location.
 * Y represents the line number from top.
 *
 * @param x It Specifies horizontal position
 *
 * @param y It Specifies vertical position (line number)
 *
 * @warning It might not work with all the LCD Dipslays. Tested on 20x4 16x2 LCD displays.
 */
void goto_xy_LCD (unsigned char x, unsigned char y);


/**
 * This function writes a char to the LCD display. (e.g WriteCharLCD ('a'); )
 *
 * @param value Specify the character to be sent [0-128 ASCII code].
 *
 * @note The function accept ASCII integer or constants 'a'..'z'.
 */
void write_char_LCD (unsigned char value);
#define WriteCharLCD write_char_LCD


/**
 * This function writes a const string to the LCD display, e.g write_message_LCD("Hello"); .
 *
 * @param buffer Is a const string written in rom (is not an array).
 *
 * @note The function accepts strings written in rom (constant), it does not accept array.
 *       To write arrays refers the write_string_LCD () function.
 *
 */



void write_message_LCD(const unsigned char *buffer);


#define WriteStringLCD write_message_LCD


/**
 * This function writes an array of char to the LCD display, terminated with /0 .
 *
 * @param buffer It is an array of char terminated with /0 .
 *
 * @note The function accepts strings  within an array. To use const array within flash use write_message_LCD ().
 *
 */
void write_string_LCD(unsigned char *buffer);
#define WriteVarLCD write_string_LCD


/**
 * This function writes an integer to the LCD display. The integer is converted to string.
 *
 * @param value It is integer that must be written to the LCD diplay.
 *
 * @param numeber_of_digits It specifies the number of shown digit [0-5].
*                    0: Left Justified
*                    1-5: Right Justified with n digit
 *
 * @note If you set a number of digit less than required the digit will be lost starting from the less
 *       significant digit. Minus is like a digit.
 *
 */
void write_integer_LCD(int value, int number_of_digits);
#define WriteIntLCD write_integer_LCD



void write_float_LCD(float value);
#define WriteFloatLCD write_float_LCD
/**
 * This Function cleans the LCD display.
 *
 */
void clear_LCD (void);
#define ClearLCD clear_LCD


/**
 * This function controls the cursor option (blinking, active)
 *
 * @param active Activate the cursor, showing it or not [TURN_ON_CURSOR, TURN_OFF_CURSOR]
 *
 * @param blinking  Let the cursor blink [BLINKING_ON,BLINKING_OFF]
 *
 * @note You must use the constant TURN_ON_CURSOR, TURN_OFF_CURSOR, BLINKING_ON, BLINKING_OFF
 *       to ensure the compatibility with LCD_44780_I2C library.
 *
 */
void cursor_LCD(unsigned char active, unsigned char blinking);
#define CursorLCD cursor_LCD


/**
 * This function controls the backligth LED.
 *
 * @param active Activate the LED backlight [TURN_ON_LED_LCD, TURN_OFF_LED_LCD]
 *
 * @param blinking  Let the cursor blink [BLINKING_ON,BLINKING_OFF]
 *
 * @note You must use the constant TURN_ON_LED_LCD, TURN_OFF_LED_LCD
 *       to ensure the compatibility with LCD_44780_I2C library.
 */
void backlight_LCD(unsigned char active);
#define BacklightLCD backlight_LCD


/**
 * This funnction initializes the LCD to work in 4 bit modality.
 *
 * @param quartz_frequency Quartz freq. expressed in MHz used to run the CPU.
 *
 *
 * @note You must properly set the microcontroller pins using the TRISx registers
 *       The library requires the delay library to be included.
 */
void  initialize_LCD(void);
#define OpenLCD initialize_LCD


void SetPinLCD(void);
float c = 1029.1;

void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xS_SysCtrl.c file.
    InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the F2837xS_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
    InitGpio();
    GPIO_SetupPinMux(13, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(13, GPIO_OUTPUT, GPIO_PUSHPULL);
    SetPinLCD();
    initialize_LCD();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
    DINT;

// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xS_PieCtrl.c file.
    InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xS_DefaultIsr.c.
// This function is found in F2837xS_PieVect.c.
    InitPieVectTable();

// Enable global Interrupts and higher priority real-time debug events:
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

// Step 6. IDLE loop. Just sit and loop forever (optional):
    for(;;)
    {
        //
        // Turn on LED
        //
    	GPIO_WritePin(13, 0);
        //
        // Delay for a bit.
        //
    	DELAY_US(100000);
    	write_integer_LCD(-100,5);


    	goto_line_LCD(2);
    	//write_string_LCD("Siamo a Cento");
    	write_float_LCD(c);

    	home_LCD();
        //
        // Turn off LED
        //
    	GPIO_WritePin(13, 1);
        //
        // Delay for a bit.
        //
    	DELAY_US(100000);
    }
}

void SetPinLCD(void)
{
	GPIO_SetupPinMux(41, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(41, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(71, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(71, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(89, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(89, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(90, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(90, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(72, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(72, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(78, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(78, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(65, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(65, GPIO_OUTPUT, GPIO_PUSHPULL);
	GPIO_SetupPinMux(43, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(43, GPIO_OUTPUT, GPIO_PUSHPULL);
}


//************************************************************
//                  enable_pulse_LCD  Implementation
//************************************************************
void enable_pulse_LCD (void) {

	GPIO_WritePin(LCD_E, 1);
	DELAY_US(1000);
	GPIO_WritePin(LCD_E, 0);
	DELAY_US(1000);
}


//************************************************************
//                  send_command_LCD  Implementation
//************************************************************
void send_command_LCD (unsigned char D3, unsigned char D2, unsigned char D1, unsigned char D0) {

	GPIO_WritePin(LCD_D0, D0);
	GPIO_WritePin(LCD_D1, D1);
	GPIO_WritePin(LCD_D2, D2);
	GPIO_WritePin(LCD_D3, D3);
	enable_pulse_LCD ();
}


//************************************************************
//                  home_LCD  Implementation
//************************************************************
void home_LCD(void) {

	send_command_LCD (0,0,0,0);
	send_command_LCD (0,0,1,0);
}


//************************************************************
//                  shift_LCD  Implementation
//************************************************************
void shift_LCD(unsigned char shift, unsigned char number_of_shift) {

	unsigned char i;

	for (i=0; i < number_of_shift; i++) {
		send_command_LCD (0,0,0,1);
		send_command_LCD (1,shift,0,0);
	}
}


//************************************************************
//                  shift_cursor_LCD  Implementation
//************************************************************
void shift_cursor_LCD(unsigned char shift, unsigned char number_of_shift){

	unsigned char i;

	for (i=0; i < number_of_shift; i++) {
		send_command_LCD (0,0,0,1);
		send_command_LCD (0,shift,0,0);
	}
}

//************************************************************
//                  goto_line_LCD  Implementation
//************************************************************
void goto_line_LCD (unsigned char line) {

switch(line) {

	case 1: send_command_LCD(1,0,0,0);
		send_command_LCD(0,0,0,0);
			break;

	case 2: send_command_LCD(1,1,0,0);
		send_command_LCD(0,0,0,0);
			break;

	case 3: send_command_LCD(1,0,0,1);
		send_command_LCD(0,1,0,0);
			break;

	case 4: send_command_LCD(1,1,0,1);
                send_command_LCD(0,1,0,0);
	}
}


//************************************************************
//                  goto_xy_LCD  Implementation
//************************************************************
void goto_xy_LCD (unsigned char x, unsigned char y){

    goto_line_LCD (y);
    shift_cursor_LCD (RIGHT, x-1);
}

//************************************************************
//                  write_char_LCD  Implementation
//************************************************************
void write_char_LCD (unsigned char value) {

	unsigned char D3,D2,D1,D0;

	GPIO_WritePin(LCD_RS, 1);

	// Splitting of the first nibble
	D3 = (value & 0b10000000) >> 7;
	D2 = (value & 0b01000000) >> 6;
	D1 = (value & 0b00100000) >> 5;
	D0 = (value & 0b00010000) >> 4;

	send_command_LCD (D3,D2,D1,D0);

	// Splitting of the second nibble
	D3 = (value & 0b00001000) >> 3;
	D2 = (value & 0b00000100) >> 2;
	D1 = (value & 0b00000010) >> 1;
	D0 = (value & 0b00000001);

	send_command_LCD (D3,D2,D1,D0);

	GPIO_WritePin(LCD_RS, 0);
}

//************************************************************
//                  write_message_LCD  Implementation
//************************************************************
void write_message_LCD(const unsigned char *buffer) {

	 // Write data to LCD up to null
    while(*buffer) {

	    // Write character to LCD
	    write_char_LCD(*buffer);
	    // Increment buffer
	    buffer++;
   }
}


//************************************************************
//                  write_string_LCD  Implementation
//************************************************************
void write_string_LCD(unsigned char *buffer) {

	// Write data to LCD up to null
	while(*buffer){

		// Write character to LCD
		write_char_LCD(*buffer);
		// Increment buffer
		buffer++;
	}
}

//************************************************************
//                  write_integer_LCD  Implementation
//************************************************************
void write_integer_LCD(int value, int number_of_digits){

	// The array size is 5 plus end of string \0
	 unsigned char convertedInt [6] = {0,0,0,0,0,0};

	// Index used to shift to the right the digit
	unsigned char index;

	// Integer is converted to string
        //snprintf((char*)convertedInt, number_of_digits, "%d", value);	//da vedere bene il tipo di cast da fare, se a char o unsigned char (vedi differenze con itoa XC8 compiler)
        ltoa(value, (char*) convertedInt);
        if (number_of_digits >0 ) {

		convertedInt[number_of_digits] = '\0';

		// Shift the digit to the right removing the empty one
		while (!isdigit(convertedInt[number_of_digits-1]))
                while (!(convertedInt[number_of_digits-1] <= '9' && convertedInt[number_of_digits-1] >= '0')){

			for (index = number_of_digits-1; index > 0; index--){
				convertedInt[index] = convertedInt[index-1];
				convertedInt[index-1] = ' ';
			}
		}
	}

	write_string_LCD (convertedInt);

}


//************************************************************
//                  clear_LCD  Implementation
//************************************************************
void clear_LCD (void){

	send_command_LCD (0,0,0,0);
	send_command_LCD (0,0,0,1);
}

//************************************************************
//                  cursor_LCD  Implementation
//************************************************************
void cursor_LCD(unsigned char active, unsigned char blinking) {

	send_command_LCD (0,0,0,0);
	send_command_LCD (1,1,active,blinking);
}

//************************************************************
//                  back_light_LCD  Implementation
//************************************************************
void backlight_LCD (unsigned char active) {

	GPIO_WritePin(LCD_LED, active);
}

//************************************************************
//                  initialize_LCD  Implementation
//************************************************************
void  initialize_LCD(void) {



	GPIO_WritePin(LCD_RS, 0);
	GPIO_WritePin(LCD_E, 0);
	GPIO_WritePin(LCD_RW, 0);

	DELAY_US(100000);

        send_command_LCD (0,0,1,1);

	DELAY_US(100000);

	send_command_LCD (0,0,1,1);

	DELAY_US(10000);

	send_command_LCD (0,0,1,1);

	send_command_LCD (0,0,1,0);

        send_command_LCD (0,0,1,0);
	send_command_LCD (1,0,0,0);

	send_command_LCD (0,0,0,0);
        send_command_LCD (1,0,0,0);

	send_command_LCD (0,0,0,0);
	send_command_LCD (0,0,0,1);

        send_command_LCD (0,0,0,0);
	send_command_LCD (0,1,1,0);

	clear_LCD ();

        cursor_LCD (0,0);

}

void write_float_LCD(float value){

	char j=0; //Variabile di conteggio ciclo for
	char Cifre_Int;	//numero di cifre intere contenute nel valore value passato alla funzione
	double appoggio; //variabile di appoggio di tipo float
	int value_int;	//valore intero da plottare



	if((value>=0.0000)&&(value<=9.9999))  // 0.0000--9.9999  4 cifre decimali, 1 cifra intera		//
			Cifre_Int=1;																			//
																									//
	else if((value>=10.000)&&(value<=99.999)) //10.000--99.99    3 cifre decimali, 2 cifre intere	//
			Cifre_Int=2;																			//
																									// NB: LA SOMMA TOTALE DELLE CIFRE è SEMPRE 5
	else if((value>=100.00)&&(value<=999.99)) //100.0--999.9  2 cifra decimale, 3 cifre intere		//
			Cifre_Int=3;																			//
																									//
	else if((value>=1000.0)&&(value<=9999.9)) //100.0--999.9  1 cifra decimale, 4 cifre intere		//
				Cifre_Int=4;																		//



	value_int = value; //prende la parte intera di value e la assegna a value_int




	write_integer_LCD(value_int,Cifre_Int); //scrive sul display la parte intera value_int con un numero di caratteri pari a Cifre_Int
	write_char_LCD ('.'); //plotta il punto (se preferite potete scrivere la virgola )



	for(j=0; j<=(5-Cifre_Int); j++) //plotta le cifre decimali trattandole come interi
	{
	appoggio = value_int; //appoggio è di tipo float, value_int viene convertito in float
			value = value-appoggio; //faccio la differenza tra value e appoggio: rimane solo la parte frazionaria: NB è ancora un numero float
				value = value*10; //moltiplico la parte frazionaria per 10 e quindi avrò una cifra intera (la prima dopo la virgola)
			value_int = value;  //assegno value appena ottenuto ad un int di appoggio quindi si perde la parte frazionaria
	write_integer_LCD(value_int,1); // plotto la prima cifra dopo la virgola (ormai diventata un numero intero)


	} //ripeto il ciclo per un numero di volte pari alle cifre decimali (5-Cifre_Int)
}
