/*
 * uart2usb.c
 *
 *  Created on: Jan 21, 2017
 *      Author: User
 */

#include "uart2usb.h"

uart_status_t UART_SendIrq(uint8_t *buff)
{
	buff[UART_INDEX_ID] = irqCountRead;
	buff[1] = ( (irqOldCount & 0xFF000000) >> 24);
	buff[2] = ( (irqOldCount & 0x00FF0000) >> 16);
	buff[3] = ( (irqOldCount & 0x0000FF00) >> 8);
	buff[4] = ( (irqOldCount & 0x000000FF) >> 0);

	return UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT);
}

uart_status_t UART_SelectVoltageSource(LTC3335_Config *drvConfig, uint8_t *buff)
{
	if( (buff[UART_SETVOLTSOURCE_ID] != InternalVoltage) &&
			(buff[UART_SETVOLTSOURCE_ID] != ExternalVoltage) )
	{
		return kStatus_UART_Fail;
	}
	return (LTC3335_SelectVoltageSource(drvConfig, buff[UART_SETVOLTSOURCE_ID]) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_SetOutVoltage(LTC3335_Config *drvConfig, const uint8_t *buff)
{
	if( (buff[UART_SETVOLTVALUE_ID] != OUT_1V8) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_2V5) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_2V8) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_3V0) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_3V3) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_3V6) &&
			(buff[UART_SETVOLTVALUE_ID] != OUT_4V5)	&&
			(buff[UART_SETVOLTVALUE_ID] != OUT_5V0)	)
	{
		return kStatus_UART_Fail;
	}

	return (LTC3335_SetOutVoltage(drvConfig, buff[UART_SETVOLTVALUE_ID]) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_SetPrescaler(LTC3335_Config *drvConfig, uint8_t *buff)
{
	if(buff[UART_SETPRESCALER_ID] > LTC3335_PRESCALER_MAX)
	{
		return kStatus_UART_Fail;
	}
	return (LTC3335_SetPrescaler(drvConfig, buff[UART_SETVOLTVALUE_ID]) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_ReadAccumCharge(LTC3335_Config *drvConfig, uint8_t *buff)
{
	if(LTC3335_GetAccumCharge(drvConfig) != kStatus_I2C_Success)
	{
		return kStatus_UART_Fail;
	}

	buff[UART_INDEX_ID] = ltc3335GetAccumCharge;
	buff[UART_ACCU_CHARGE_ID] = *(drvConfig->AccumulatedCharge);

	return UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT);
}

uart_status_t UART_WriteAccumCharge(LTC3335_Config *drvConfig, const uint8_t *buff)
{
	LTC3335_SetAccumCharge(drvConfig, buff[UART_ACCU_CHARGE_ID]);

	return kStatus_UART_Success;
}

uart_status_t UART_GetAlarms(LTC3335_Config *drvConfig, uint8_t *buff)
{
	if(LTC3335_GetAlarms(drvConfig) != kStatus_I2C_Success)
	{
		return kStatus_UART_Fail;
	}

	buff[UART_INDEX_ID] = ltc3335GetAlarms;
	buff[UART_ACCU_CHARGE_ID] = *(drvConfig->Alarms);

	return UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT);
}

uart_status_t UART_ClearInterrupt(LTC3335_Config *drvConfig)
{
	return (LTC3335_ClearInterrupt(drvConfig) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_SetCounterTest(LTC3335_Config *drvConfig)
{
	return (LTC3335_SetCounterTest(drvConfig) == kStatus_I2C_Success) ?
				kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_StopCounterTest(LTC3335_Config *drvConfig)
{
	return (LTC3335_StopCounterTest(drvConfig) == kStatus_I2C_Success) ?
				kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_StartPWM(tpm_pwm_param_t *pwmConfig, uint8_t *buff)
{
	uint32_t frequency = (buff[UART_PWM_FREQ_HBYTE_ID] << 16) |
			(buff[UART_PWM_FREQ_MBYTE_ID] << 8) |
			buff[UART_PWM_FREQ_LBYTE_ID];

	if( (buff[UART_PWM_DUTY_ID] > 100) || (frequency < 10) || (frequency > 187500))
	{
		return kStatus_UART_Fail;
	}
	TPM_DRV_PwmStop(TPM0_IDX, pwmConfig, 0);

	pwmConfig->uDutyCyclePercent = buff[UART_PWM_DUTY_ID];
	pwmConfig->uFrequencyHZ = frequency;

	return (TPM_DRV_PwmStart(TPM0_IDX, pwmConfig, 0) == kStatusTpmSuccess) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_StopPWM(tpm_pwm_param_t *pwmConfig)
{
	TPM_DRV_PwmStop(TPM0_IDX, pwmConfig, 0);
	pwmConfig->uDutyCyclePercent = 0;
	pwmConfig->uFrequencyHZ = 100;
	TPM_DRV_PwmStart(TPM0_IDX, pwmConfig, 0);
	return kStatus_UART_Success;
}

uart_status_t UART_ReadTime(DS3231_realTime* config, uint8_t *buff)
{
	if(DS3231_ReadAll(config) != kStatus_I2C_Success)
	{
		return  kStatus_UART_Fail;
	}

	buff[UART_INDEX_ID] = readTime;
	buff[UART_HOURS_ID] = config->hours;
	buff[UART_MINUTES_ID] = config->minutes;
	buff[UART_SECONDS_ID] = config->seconds;

	return UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT);
}

uart_status_t UART_ReadDate(DS3231_realTime* config, uint8_t *buff)
{
	if(DS3231_ReadAll(config) != kStatus_I2C_Success)
	{
		return  kStatus_UART_Fail;
	}

	buff[UART_INDEX_ID] = readDate;
	buff[UART_YEAR_ID] = config->year;
	buff[UART_MONTH_ID] = config->month;
	buff[UART_DATE_ID] = config->date;

	return UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT);
}

uart_status_t UART_WriteTime(DS3231_realTime* config, uint8_t *buff)
{
	config->hours = buff[UART_HOURS_ID];
	config->minutes = buff[UART_MINUTES_ID];
	config->seconds = buff[UART_SECONDS_ID];

	return (DS3231_WriteTime(config) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_WriteDate(DS3231_realTime* config, uint8_t *buff)
{
	config->date = buff[UART_DATE_ID];
	config->month = buff[UART_MONTH_ID];
	config->year = buff[UART_YEAR_ID];

	return (DS3231_WriteDate(config) == kStatus_I2C_Success) ?
			kStatus_UART_Success : kStatus_UART_Fail;
}

uart_status_t UART_EnableSaveData(save_data_t *config, uint8_t *buff)
{
	config->timePeriod = buff[UART_TIMECYKLE_DATA_ID];
	if( (config->timePeriod > 60) || (config->timePeriod < 1) )
	{
		return kStatus_UART_Fail;
	}

	irqCount = 0;
	PIT_DRV_SetTimerPeriodByUs(pitTimer1_IDX, pitTimer1_CHANNEL, (config->timePeriod) * 1000000);
	GPIO_DRV_ClearPinOutput(LEDRGB_GREEN);
	GPIO_DRV_SetPinOutput(MEASURE_LED);

	uint8_t voutPart1 = 0;
	uint8_t voutPart2 = 0;
	switch(drvConfig.OutVoltage)
	{
		case OUT_1V8:
			voutPart1 = 1;
			voutPart2 = 8;
			break;
		case OUT_2V5:
			voutPart1 = 2;
			voutPart2 = 5;
			break;
		case OUT_2V8:
			voutPart1 = 2;
			voutPart2 = 8;
			break;
		case OUT_3V0:
			voutPart1 = 3;
			voutPart2 = 0;
			break;
		case OUT_3V3:
			voutPart1 = 3;
			voutPart2 = 3;
			break;
		case OUT_3V6:
			voutPart1 = 3;
			voutPart2 = 6;
			break;
		case OUT_4V5:
			voutPart1 = 4;
			voutPart2 = 5;
			break;
		case OUT_5V0:
			voutPart1 = 5;
			voutPart2 = 0;
			break;
		default:
			break;
	}
	PRINTF("#*#\r\n");
	PRINTF("Vout= %d.%d\r\n", voutPart1, voutPart2);
	PRINTF("M= %d\r\n", drvConfig.Prescaler);
	PRINTF("Tvz= %d\r\n", config->timePeriod);
	PRINTF("PWMduty= %d\r\n", tpmTmr1_ChnConfig0.uDutyCyclePercent);
	PRINTF("PWMfreq= %d\r\n", tpmTmr1_ChnConfig0.uFrequencyHZ);
	PRINTF("Rload= %d\r\n", RloadEnable);
	PRINTF("##**##\r\n");

	return kStatus_UART_Success;
}

uart_status_t UART_DisableSaveData(save_data_t *config)
{
	config->saveDataFlag = false;
	PIT_DRV_SetTimerPeriodByUs(pitTimer1_IDX, pitTimer1_CHANNEL, 1000000);

#ifdef LPTMR_USED
	LPTMR_DRV_Stop(LPTMR0_IDX);
	LPTMR_DRV_SetTimerPeriodUs(LPTMR0_IDX, 1000000);
	LPTMR_DRV_Start(LPTMR0_IDX);
#endif

	return kStatus_UART_Success;
}

uart_status_t UART_SaveMeasurementNote(uint8_t *buff)
{
	uart_status_t status = kStatus_UART_Success;
	uint8_t noteBuff[UART_NOTE_LENGTH_BUFF] = {};
	uint32_t noteSize = (buff[UART_NOTE_MSB_BUFF] << 8) + buff[UART_NOTE_LSB_BUFF];

	uint8_t ack = UART_ACK;
	UART_DRV_SendDataBlocking(UART1_IDX, &ack, UART_ACK_LENGTH, UART_TIMEOUT);

	status = UART_DRV_ReceiveDataBlocking(UART1_IDX, noteBuff, noteSize, 2000);
	if(status != kStatus_UART_Success)
	{
		PRINTF("status: %d\nPocet: %d\n0x%x 0x%x 0x%x 0x%x 0x%x\n", status, noteSize, buff[0], buff[1], buff[2], buff[3], buff[4]);
		return status;
	}
	for(uint32_t j = 0; j < noteSize; j++)
	{
		PRINTF("%c", noteBuff[j]);
	}
	PRINTF("\r\n###***###\r\n");
	PRINTF("yyyy-mm-dd\thh-mm-ss\tacc\tIRQ\ttemp\tVin\r\n");

	return status;
}

uart_status_t UART_Ltc3335TurnOn(LTC3335_Config *drvConfig, save_data_t *config, uint8_t *buff)
{
	if(buff[LTC3335_EN_IDX])
	{
		PIT_DRV_StopTimer(pitTimer1_IDX, pitTimer1_CHANNEL);
		PIT_DRV_SetTimerPeriodByUs(pitTimer1_IDX, pitTimer1_CHANNEL, (config->timePeriod) * 1000000);

		GPIO_DRV_ClearPinOutput(LEDRGB_GREEN);
		GPIO_DRV_SetPinOutput(MEASURE_LED);
		config->saveDataFlag = true;
		PIT_DRV_StartTimer(pitTimer1_IDX, pitTimer1_CHANNEL);

		LTC3335_Enable(drvConfig, true);
	}
	else
	{
		GPIO_DRV_SetPinOutput(LEDRGB_GREEN);
		GPIO_DRV_ClearPinOutput(MEASURE_LED);
		PIT_DRV_StopTimer(pitTimer1_IDX, pitTimer1_CHANNEL);
		PIT_DRV_SetTimerPeriodByUs(pitTimer1_IDX, pitTimer1_CHANNEL, 1000000);
		UART_StopPWM(&tpmTmr1_ChnConfig0);
		LTC3335_Enable(drvConfig, false);
		config->saveDataFlag = false;
		GPIO_DRV_ClearPinOutput(RLOAD_PIN);
	}

	return kStatus_UART_Success;
}

void UART_Routine(LTC3335_Config *drvConfig, DS3231_realTime *timeConfig ,save_data_t *saveDataConfig)
{
	uart_status_t status = kStatus_UART_Success;
	uint8_t buff[UART_FRAME_LENGTH] = {};

	if(UART_DRV_ReceiveDataBlocking(UART1_IDX, buff, UART_FRAME_LENGTH, UART_TIMEOUT) !=
			kStatus_UART_Success)
	{
		return;
	}

	switch(buff[UART_INDEX_ID])
	{
		case noAction:
			return;
		case irqCountRead:
			status = UART_SendIrq(buff);
			break;
		case ltc3335SelectVoltageSource:
			status = UART_SelectVoltageSource(drvConfig, buff);
			break;
		case ltc3335SetOutVoltage:
			status = UART_SetOutVoltage(drvConfig, buff);
			break;
		case ltc3335SetPrescaler:
			status = UART_SetPrescaler(drvConfig, buff);
			break;
		case ltc3335GetAccumCharge:
			status = UART_ReadAccumCharge(drvConfig, buff);
			break;
		case ltc3335SetAccumCharge:
			status = UART_WriteAccumCharge(drvConfig, buff);
			break;
		case ltc3335GetAlarms:
			status = UART_GetAlarms(drvConfig, buff);
			break;
		case ltc3335ClearInterrupt:
			status = UART_ClearInterrupt(drvConfig);
			break;
		case ltc3335SetCounterTest:
			status = UART_SetCounterTest(drvConfig);
			break;
		case ltc3335StopCounterTest:
			status = UART_StopCounterTest(drvConfig);
			break;
		case pwmStart:
			status = UART_StartPWM(&tpmTmr1_ChnConfig0, buff);
			break;
		case pwmStop:
			status = UART_StopPWM(&tpmTmr1_ChnConfig0);
			break;
		case readTime:
			status = UART_ReadTime(timeConfig, buff);
			break;
		case readDate:
			status = UART_ReadDate(timeConfig, buff);
			break;
		case writeTime:
			status = UART_WriteTime(timeConfig, buff);
			break;
		case writeDate:
			status = UART_WriteDate(timeConfig, buff);
			break;
		case saveDataEnable:
			status = UART_EnableSaveData(saveDataConfig, buff);
			break;
		case saveDataDisable:
			status = UART_DisableSaveData(saveDataConfig);
			break;
		case saveMeasuremenNote:
			status = UART_SaveMeasurementNote(buff);
			break;
		case ltc3335TurnOn:
			status = UART_Ltc3335TurnOn(drvConfig, saveDataConfig, buff);
			break;
		case rLoadOnOff:
				RloadEnable = (bool)buff[1];
				GPIO_DRV_WritePinOutput(RLOAD_PIN, RloadEnable);
			break;
		default:
			status = kStatus_UART_Fail;
			break;
	}

	buff[UART_ACK_ID] = (status == kStatus_UART_Success) ? UART_ACK : UART_NACK;
	UART_DRV_SendDataBlocking(UART1_IDX, buff, UART_ACK_LENGTH, UART_TIMEOUT);
	//PRINTF("ACK: %d\n", status);
	buff[UART_INDEX_ID] = noAction;

	return;
}
