// ==========================================================================
// usb.c
// (c) 2020, Aurel Dumitru
//
// Description:
// USB functionality
// =========================================================================


#include "devstatus.h"
#include "sensor_nfc.h"
#include "detect_lowpower.h"
#include "sensor_rs485.h"
#include "sensor_raing.h"
#include "sensor_analog.h"
#include "calibrations.h"

uint32_t DevStatus_InitPhase;
__attribute__((section(".status_data_sec"))) uint32_t DevStatus[128];


void DevStatus_Init(void)
{
	DevStatus_InitPhase = DEVSTATUS_UNKNOWN_INIT_VALUE;
	if ((DevStatus[DEVSTATUS_VALID_KEY1_IDX] == 0xCAFEFACE) && (DevStatus[DEVSTATUS_VALID_KEY2_IDX] == 0xA5A5A5A5))
		DevStatus[DEVSTATUS_RESET_COUNTER_IDX]++;
	else
	{
		DevStatus[DEVSTATUS_POWERON_STATUS_IDX]			= DEVSTATUS_POWERON_TRUE;
		DevStatus[DEVSTATUS_RESET_COUNTER_IDX]			= 0;
		DevStatus[DEVSTATUS_MOTOR1_STATUS_IDX]			= DEVSTATUS_MOTOR_OPENLOAD;
		DevStatus[DEVSTATUS_MOTOR2_STATUS_IDX]			= DEVSTATUS_MOTOR_OPENLOAD;
		DevStatus[DEVSTATUS_MOTORS_COUNTER_IDX]			= 0;
		DevStatus[DEVSTATUS_PICTURES_COUNTER_IDX]		= 0;
		DevStatus[DEVSTATUS_BAT_STATUS_IDX]				= DEVSTATUS_BAT_OK;
		DevStatus[DEVSTATUS_RAIN_DETECTED_STATUS_IDX]	= DEVSTATUS_RAIN_DETECTED_NO;

		DevStatus[DEVSTATUS_R0_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_R1_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_R2_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_R3_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_R12_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_LR_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_PC_FAULT_STATUS_IDX]		= 0;
		DevStatus[DEVSTATUS_PSR_FAULT_STATUS_IDX]		= 0;

		DevStatus[DEVSTATUS_VALID_KEY1_IDX]				= 0xCAFEFACE;
		DevStatus[DEVSTATUS_VALID_KEY2_IDX]				= 0xA5A5A5A5;
	}

	if ((DevStatus[DEVSTATUS_SENSORS_VALID_KEY1_IDX] != 0xBADEDACE) ||
		(DevStatus[DEVSTATUS_SENSORS_VALID_KEY2_IDX] != 0xDADADADA))
	{
		for (uint32_t I=DEVSTATUS_SENSORS_RS485_STATUS_IDX; I<DEVSTATUS_SENSOR_RGAUGE_STATUS_IDX; I++)
			DevStatus[I] = SENSOR_RS485_NOT_CHECKED;
		DevStatus[DEVSTATUS_SENSOR_RGAUGE_STATUS_IDX]	= SENSOR_RAING_NOT_CHECKED;
		DevStatus[DEVSTATUS_SENSOR_ANALOG_STATUS_IDX]	= SENSOR_ANALOG_NOT_CHECKED;
	}
}


void DevStatus_SetInitPhase(uint32_t InitPhase)
{
	DevStatus_InitPhase = InitPhase;
}


void DevStatus_WriteNfcStatus(void)
{
	// Get IR value
	DevStatus[DEVSTATUS_INFRARED_STATUS_IDX] = DEVSTATUS_INFRARED_OK;
	uint32_t IrAverage = Detect_GetIrAverage();
	if (IrAverage != 0xFF)
		if (((100*IrAverage)/NC_IR_BASE_VALUE) < 65)
			DevStatus[DEVSTATUS_INFRARED_STATUS_IDX] = DEVSTATUS_INFRARED_LOW;

	// do the NFC saving
	Sensor_Nfc_PowerUp();
	Sensor_Nfc_UpdateLinkDiag();
	Sensor_Nfc_PowerDown();
}

uint32_t DevStatus_GetBoardType(void)
{
	return READ_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);
}


void DevStatus_SetDeviceType(uint32_t ForceSensorType)
{
	  if (((DevStatus[DEVSTATUS_CAMERA_STATUS_IDX] == DEVSTATUS_CAMERA_COM_FAIL) && (DevStatus[DEVSTATUS_HYPERRAM_STATUS_IDX] == DEVSTATUS_HYPERRAM_FAIL)) ||
		  ForceSensorType)
	  {
		  DevStatus[DEVSTATUS_HYPERRAM_STATUS_IDX] = DEVSTATUS_HYPERRAM_OK;
		  DevStatus[DEVSTATUS_CAMERA_STATUS_IDX] = DEVSTATUS_CAMERA_OK;
		  DevStatus[DEVSTATUS_MOTOR1_STATUS_IDX] = DEVSTATUS_MOTOR_OK;
		  DevStatus[DEVSTATUS_MOTOR2_STATUS_IDX] = DEVSTATUS_MOTOR_OK;
		  DevStatus[DEVSTATUS_INSECTS_VS_SENSORS_IDX] = 0;
	  }
	  else
		  DevStatus[DEVSTATUS_INSECTS_VS_SENSORS_IDX] = 1;
}

uint32_t DevStatus_IsDeviceTypeInsectTrap(void)
{
	return DevStatus[DEVSTATUS_INSECTS_VS_SENSORS_IDX];
}


void DevStatus_SaveStackAndReset(uint32_t* Stack)
{
	DevStatus[DEVSTATUS_R0_FAULT_STATUS_IDX]	= Stack[0];
	DevStatus[DEVSTATUS_R1_FAULT_STATUS_IDX]	= Stack[1];
	DevStatus[DEVSTATUS_R2_FAULT_STATUS_IDX]	= Stack[2];
	DevStatus[DEVSTATUS_R3_FAULT_STATUS_IDX]	= Stack[3];
	DevStatus[DEVSTATUS_R12_FAULT_STATUS_IDX]	= Stack[4];
	DevStatus[DEVSTATUS_LR_FAULT_STATUS_IDX]	= Stack[5];
	DevStatus[DEVSTATUS_PC_FAULT_STATUS_IDX]	= Stack[6];
	DevStatus[DEVSTATUS_PSR_FAULT_STATUS_IDX]	= Stack[7];

	switch(DevStatus_InitPhase)
	{
		case DEVSTATUS_HYPERRAM_INIT_VALUE:
			DevStatus[DEVSTATUS_HYPERRAM_STATUS_IDX] = DEVSTATUS_HYPERRAM_FAIL;
			return;
		case DEVSTATUS_OSC32_INIT_VALUE:
			DevStatus[DEVSTATUS_OSC32_STATUS_IDX] = DEVSTATUS_OSC32_FAIL;
			return;
	}
	while(1); // wait for WDT reset
}
