/*
 * my_GPIO.c
 *
 *  Created on: gg/mmm/ccaa
 *      Author: cognome.nome
 *
 * funzioni per gestire gli ingressi e uscite digitali
 *
 */

//==============================================================================
// Include files

#include "string.h"
#include "stdbool.h"
#include "stdint.h"
#include "stdlib.h"

#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_uart.h"

#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/uart.h"

#include "utils/uartstdio.h"
#include "utils/uartstdio.c"

#include "my_GPIO.h"

//==============================================================================
// Constants

//==============================================================================
// Types

typedef struct
{
	union
	{
   		struct
    	{
			unsigned char bit_1_4     :  4;
			unsigned char bit_5_8     :  4;
    	};
   		unsigned char bits;
  	};//union_bits;
}S_bits;

//==============================================================================
// Static global variables

static S_out out_internal_0;
static S_out out_internal_1;
static S_out out_internal_2;

//==============================================================================
// Static functions

static void InitInterruptInput(void)
{
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT); // PT0: MOD1_IN1 // PT1: MOD1_IN2 // PT2: MOD1_IN3 // PT3: MOD1_IN4 // CN2
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); // PP0: MOD2_IN1 // PP1: MOD2_IN2 // PP2: MOD2_IN3 // PP3: MOD2_IN4 // CN4
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // PB4: MOD3_IN1 // PB5: MOD3_IN2 // PB6: MOD3_IN3 // PB7: MOD3_IN4 // CN3

	// MOD1 CN2
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
	GPIOPadConfigSet(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); // Push-pull
    ROM_GPIOIntTypeSet(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, GPIO_BOTH_EDGES);
    ROM_GPIOIntEnable(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
    ROM_IntEnable(INT_GPIOT);

	// MOD2 CN4
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
	GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); // Push-pull
    ROM_GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, GPIO_BOTH_EDGES);
    ROM_GPIOIntEnable(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
    ROM_IntEnable(INT_GPIOP0);

	// MOD3 CN3
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);
	GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); // Push-pull
    ROM_GPIOIntTypeSet(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4, GPIO_BOTH_EDGES);
    ROM_GPIOIntEnable(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);
    ROM_IntEnable(INT_GPIOB);
}

static void InitInterruptSelector(void)
{
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);

	ROM_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_2);
	GPIOPadConfigSet(GPIO_PORTQ_BASE,  GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); // Push-pull
    ROM_GPIOIntTypeSet(GPIO_PORTQ_BASE, GPIO_PIN_2, GPIO_BOTH_EDGES);
    ROM_GPIOIntEnable(GPIO_PORTQ_BASE, GPIO_PIN_2);
    ROM_IntEnable(INT_GPIOQ0);
}

static void GPIOPinUnlockGPIO(uint32_t ui32Port, uint8_t ui8Pins)
{
    HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY;      // Unlock the port
    HWREG(ui32Port + GPIO_O_CR) |= ui8Pins;             // Unlock the Pin
    HWREG(ui32Port + GPIO_O_LOCK) = 0;                  // Lock the port
}

//==============================================================================
// Global variables

//==============================================================================
// Global functions

inline void GPIO_set_COMANDO_VENTOLA(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, value);
}

/*
inline void GPIO_set_REL_1(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, value);
}
*/

// farlo diventare un interrupt
inline unsigned long GPIO_SEL_PROG_RUN_read(void)
{
	return (ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_PIN_2) >> 2);
}

/* Configurazione GPIO iniziale */
long GPIO_init(void)
{
	//----------------------------
	// Enable periferiche
	//----------------------------
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlDelay(3);


	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT);

	//-----------------------------------
	//CONFIGURAZIONE UART-SERIALE RS232
	//-----------------------------------
	// spostato nella funzione -> void UartInit(void)

	//-----------------------------------
	// Configuro i GPIO per i moduli I/O
	//-----------------------------------

	//--------------------------------------------------------------------------------------------------
	// MODULO 1
	//--------------------------------------------------------------------------------------------------
	// PT0 -  MOD1_IN1
	// PT1 -  MOD1_IN2
	// PT2 -  MOD1_IN3
	// PT3 -  MOD1_IN4
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

	// PE0 -  MOD1_OUT1
	// PE1 -  MOD1_OUT2
	// PE2 -  MOD1_OUT3
	// PE3 -  MOD1_OUT4
	// PE4 -  MOD1_OUT5
	// PE5 -  MOD1_OUT6
	// PE6 -  MOD1_OUT7
	// PE7 -  MOD1_OUT8
	GPIOPinUnlockGPIO(GPIO_PORTE_BASE, GPIO_PIN_7);
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

	// PS0 -  MOD1_OUT9
	// PS1 -  MOD1_OUT10
	// PS2 -  MOD1_OUT11
	// PS3 -  MOD1_OUT12
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
	//--------------------------------------------------------------------------------------------------

	//--------------------------------------------------------------------------------------------------
	// MODULO 2
	//--------------------------------------------------------------------------------------------------
	// PP0 -  MOD2_IN1
	// PP1 -  MOD2_IN2
	// PP2 -  MOD2_IN3
	// PP3 -  MOD2_IN4
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

	// PD0 -  MOD2_OUT1
	// PD1 -  MOD2_OUT2
	// PD2 -  MOD2_OUT3
	// PD3 -  MOD2_OUT4
	// PD4 -  MOD2_OUT5
	// PD5 -  MOD2_OUT6
	// PD6 -  MOD2_OUT7
	// PD7 -  MOD2_OUT8
	GPIOPinUnlockGPIO(GPIO_PORTD_BASE, GPIO_PIN_7);
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

	// PK0 -  MOD2_OUT9
	// PK1 -  MOD2_OUT10
	// PK2 -  MOD2_OUT11
	// PK3 -  MOD2_OUT12
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTK_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
	//--------------------------------------------------------------------------------------------------

	//--------------------------------------------------------------------------------------------------
	// MODULO 3
	//--------------------------------------------------------------------------------------------------
	// PB4 -  MOD3_IN1
	// PB5 -  MOD3_IN2
	// PB6 -  MOD3_IN3
	// PB7 -  MOD3_IN4
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);

	// PH4 -  MOD3_OUT1
	// PH5 -  MOD3_OUT2
	// PH6 -  MOD3_OUT3
	// PH7 -  MOD3_OUT4
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);

	// PJ0 -  MOD3_OUT5
	// PJ1 -  MOD3_OUT6
	// PJ2 -  MOD3_OUT7
	// PJ3 -  MOD3_OUT8
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

	// PP4 -  MOD3_OUT9
	// PP5 -  MOD3_OUT10
	// PP6 -  MOD3_OUT11
	// PP7 -  MOD3_OUT12
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);
	//--------------------------------------------------------------------------------------------------

	memset(&out_internal_0, 0, sizeof(S_out));
	memset(&out_internal_1, 0, sizeof(S_out));
	memset(&out_internal_2, 0, sizeof(S_out));

	//--------------------------------------------------------------------------------------------------
	// RELAY MICRO
	// PF0 - COMANDO VENTOLA
	// PF1 - REL_1
	//--------------------------------------------------------------------------------------------------
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_0);
	//--------------------------------------------------------------------------------------------------

	// GPIO_SEL_PROG_RUN_read
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_2);

	InitInterruptInput();
	InitInterruptSelector();

	return 0;
}

// Lettura ingressi moduli
long Read_Input_Module(unsigned long number, S_in *in)
{

	if(in == NULL)
	{
		return -1;
	}

	switch(number)
	{
		case 1:
		{
			in->in = ROM_GPIOPinRead(GPIO_PORTT_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
		}
		break;
		case 2:
		{
			in->in = ROM_GPIOPinRead(GPIO_PORTP_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);
		}
		break;
		case 3:
		{
			in->in = ROM_GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);
		}
		break;
		default:
			in->in = 0;
	}

	return 0;
}

// Lettura uscite moduli
/*
long Read_Output_Module(unsigned long number, S_out *out)
{
	if(out == NULL)
	{
		return -1;
	}

	switch(number)
	{
		case 1:
		{
			out->out = ~out_internal_0.out;
		}
		break;
		case 2:
		{
			out->out = ~out_internal_1.out;
		}
		break;
		case 3:
		{
			out->out = ~out_internal_2.out;
		}
		break;
		default:
			out->out = 0;
	}

	return 0;
}
*/

// Lettura uscite moduli
long Write_Output_Module(unsigned long number, S_out *out)
{
	if(out == NULL)
	{
		return -1;
	}

	switch(number)
	{
		case 1:
		{
			out_internal_0.out = ~(out->out);
			ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, out_internal_0.out_1_8);
			ROM_GPIOPinWrite(GPIO_PORTS_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, out_internal_0.out_9_12);
		}
		break;
		case 2:
		{
			out_internal_1.out = ~(out->out);

			ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, out_internal_1.out_1_8);
			ROM_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, out_internal_1.out_9_12);
		}
		break;
		case 3:
		{
			S_bits tmp;

			out_internal_2.out = ~(out->out);

			memset(&tmp, 0, sizeof(S_bits));
			tmp.bit_5_8 = out_internal_2.out_1_4;
			ROM_GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4, tmp.bits);
			ROM_GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0, out_internal_2.out_5_8);

			memset(&tmp, 0, sizeof(S_bits));
			tmp.bit_5_8 = out_internal_2.out_9_12;
			ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4, tmp.bits);
		}
		break;
		default:
			out->out = 0;
	}

	return 0;
}
