/*
 * my_DAC.c
 *
 *  Created on: gg/mmm/ccaa
 *      Author: cognome.nome
 *
 * funzioni per il DAC
 *
 */

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

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

#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"

#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"

#include "drivers/AD7193.h"
#include "my_GPIO.h"
#include "drivers/my_DAC.h"
#include "my_timer.h"
#include "main.h"
#include "drivers/my_semaphore.h"

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

#define WRITE_1_DAC			  0x00
#define WRITE_0_DAC		      0xFF

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

typedef struct
{
	volatile EBitCounter  counter;
	unsigned long         milliVolt;
	struct
	{
		union
		{
			struct
			{
				unsigned short BITSDAC          :  12; // LSB
				unsigned short BITSDUMMYDAC0    :  1;
				unsigned short BITSDUMMYDAC1    :  1;
				unsigned short BITSADDRESS0  	:  1;
				unsigned short BITSADDRESS1     :  1; // MSB
			};
			struct
			{
				unsigned short BIT0	            :  1; // LSB
				unsigned short BIT1      	    :  1;
				unsigned short BIT2             :  1;
				unsigned short BIT3      	    :  1;
				unsigned short BIT4           	:  1;
				unsigned short BIT5      		:  1;
				unsigned short BIT6           	:  1;
				unsigned short BIT7	            :  1;
				unsigned short BIT8	            :  1;
				unsigned short BIT9      	    :  1;
				unsigned short BIT10            :  1;
				unsigned short BIT11      	    :  1;
				unsigned short BITDUMMYDAC0     :  1;
				unsigned short BITDUMMYDAC1     :  1;
				unsigned short BITADDRESS0  	:  1;
				unsigned short BITADDRESS1      :  1; // MSB
			};
			unsigned short DataDACAll;
		};
	}DataW;
}TDAC;

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

static volatile unsigned long Timer3IntCounter = 0;
static TDAC DAC;

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

static inline void DAC_Write_Timer_Enable(void)
{
	ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
	ROM_TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
}

static inline void DAC_Write_Timer_Disable(void)
{
	ROM_TimerIntDisable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
	ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
}

static inline void GPIO_set_DAC_SCLK(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, value);
}

static inline void GPIO_set_DAC_DIN(unsigned long value) // SDI
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, value);
}

static inline void GPIO_set_DAC_CS(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, value);
}

static inline void GPIO_set_DAC_LOADDACS(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_6, value);
}

static inline void Reset_DAC(void)
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, WRITE_0_DAC);
}

static inline void Abil_DAC(void)
{
	ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, WRITE_1_DAC);
}

static long InitTimer3(void)
{
    // The Timer0 peripheral must be enabled for use.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);

    // Configure 32-bit periodic timer A.
    ROM_TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC);
    ROM_TimerLoadSet(TIMER3_BASE, TIMER_A, g_ui32SysClock/10000); // 250 (MHz) / 10 (KHz) = 25000000 (Hz) / 10000 (Hz) =  2500 (Hz) = 0,4 (ms) = 400 (ns)

    // Setup the interrupts for the timer timeouts.
    ROM_TimerIntDisable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
    ROM_IntEnable(INT_TIMER3A);

    // Enable the timers.
    ROM_TimerEnable(TIMER3_BASE, TIMER_A);

	return 0;
}

static long DACmilliVoltToBit(void)
{
	long bitTmp;

	bitTmp = round((DAC.milliVolt*4096.0f)/10000.0f);
	if(bitTmp > 4095) // 0x0FFF = 12 bit
		bitTmp = 4095; // 0x0FFF = 12 bit
	DAC.DataW.BITSDAC = bitTmp;

	return 0;
}

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

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

void InitDAC(void)
{
	memset(&DAC,0,sizeof(TDAC));
	DAC.counter = WORD_17;

	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

	// DAC_CS
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);

	// DAC_SCLK
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

	// DAC_SDI
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_4);

	// DAC_RESET
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_5);

	// DAC_LOADDACS
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_6);

	// DAC_CS -> 0
	//GPIO_set_DAC_CS(WRITE_0_DAC); //il CS va basso quando inizio la trasmissione***
	// DAC_LOADDACS -> 1
	GPIO_set_DAC_LOADDACS(WRITE_1_DAC);
	GPIO_set_DAC_SCLK(WRITE_1_DAC);

	Reset_DAC();
	ROM_SysCtlDelay(MILLI_DELAY);
	Abil_DAC();

	InitTimer3();
}

long SetDAC_ChannelA(unsigned long milliVolt)
{
	WaitSemaphore(&sem_DAC);

	DAC.DataW.BITADDRESS1 = 0;
	DAC.DataW.BITADDRESS0 = 0;

	DAC.milliVolt = milliVolt;
	DACmilliVoltToBit();
    DAC_Write_Timer_Enable();

	return 0;
}

long SetDAC_ChannelB(unsigned long milliVolt)
{
	WaitSemaphore(&sem_DAC);

	DAC.DataW.BITADDRESS1 = 0;
	DAC.DataW.BITADDRESS0 = 1;

	DAC.milliVolt = milliVolt;
	DACmilliVoltToBit();
    DAC_Write_Timer_Enable();

	return 0;
}

void Timer3_WriteDAC(void)
{
    ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);

    Timer3IntCounter++;

    switch(DAC.counter)
    {
		case 34:
		{
			GPIO_set_DAC_CS(WRITE_0_DAC); //il CS va basso quando inizio la trasmissione***
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BITADDRESS1)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 32:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BITADDRESS0)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 30:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BITDUMMYDAC1)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 28:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BITDUMMYDAC0)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 26:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BIT11)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 24:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BIT10)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 22:
		{
			GPIO_set_DAC_SCLK(WRITE_0_DAC);
			if(DAC.DataW.BIT9)
			{
				GPIO_set_DAC_DIN(WRITE_1_DAC);
			}
			else
			{
				GPIO_set_DAC_DIN(WRITE_0_DAC);
			}
			DAC.counter--;
		}break;
		case 20:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT8)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 18:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT7)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 16:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT6)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 14:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT5)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 12:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT4)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 10:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT3)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 8:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT2)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 6:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT1)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 4:
    	{
    		GPIO_set_DAC_SCLK(WRITE_0_DAC);
    	    if(DAC.DataW.BIT0)
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_1_DAC);
    	    }
    	    else
    	    {
    	    	GPIO_set_DAC_DIN(WRITE_0_DAC);
    	    }
    	    DAC.counter--;
    	}break;
		case 2:
    	{
    		GPIO_set_DAC_CS(WRITE_1_DAC); //il CS va alto quando concludo la trasmissione***
    		//GPIO_set_DAC_LOADDACS(WRITE_0_DAC);
    	    DAC.counter--;
    	}break;
		case 1:
    	{
    		GPIO_set_DAC_LOADDACS(WRITE_0_DAC);	//spostato dal case 2 al case 1 per gestione CS***
    		//GPIO_set_DAC_LOADDACS(WRITE_1_DAC);
    		DAC.counter--;
    	}break;
		case 0:
    	{
    		GPIO_set_DAC_LOADDACS(WRITE_1_DAC);	//spostato dal case 1 al case 0 per gestione CS***
    		DAC_Write_Timer_Disable();
    		DAC.counter = WORD_17;
    		ReleaseSemaphore(&sem_DAC);
    	}break;
    	// dato valido
		case 33:
		case 31:
		case 29:
		case 27:
		case 25:
		case 23:
		case 21:
		case 19:
		case 17:
		case 15:
		case 13:
		case 11:
		case 9:
		case 7:
		case 5:
		case 3:
    	{
    		GPIO_set_DAC_SCLK(WRITE_1_DAC);
    		DAC.counter--;
    	}break;
		default:{}break;
    }
}
