/*! Time-stamp: <@(#)ATDemoTunDVBT2.cpp   07/02/2011 - 08:00:00   P.Hoogervorst>
 *********************************************************************
 *  @file   : ATDemoTunDVBT2.cpp
 *
 *  Project : ATDemoApp. Testappliction for Alitronika devices.
 *			  Supports Linux and windows operating System.
 *
 *  Package : 
 *
 *  Company : Engineering Spirit
 *
 *  Author  : P.Hoogervorst                              Date: 07/05/2007
 *
 *  Purpose : Implementation of methods for class 
 *
 *********************************************************************
 * Version History:
 *
 * V 0.10  07/02/2011  BN : First Revision
 *
 *********************************************************************
 */

/**********************************************************************************************************/
// operating system specific operations
#ifndef LINUX
#pragma warning (disable : 4996)
#pragma warning (disable : 4005)
#endif

/**********************************************************************************************************/
// includes
#include <stdio.h>
#include "ATDemo.h"

/**********************************************************************************************************/
// static strings
static const char *strGuard[] =
{
	"1/32   ",
	"1/16   ",
	"1/8    ",
	"1/4    ",
	"1/128  ",
	"19/128 ",
	"19/256 ",
	"RSVD1  ",
	"INVALID"
};
#define SIZEOF_GUARD_STR	sizeof(strGuard)/sizeof(strGuard[0])

static const char *strConst[] =
{
	"BPSK   ",
	"QPSK   ",
	"QAM16  ",
	"QAM64  ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"RSVD5  ",
	"RSVD6  ",
	"RSVD7  ",
	"RSVD8  ",
	"RSVD9  ",
	"RSVD10 ",
	"RSVD11 ",
	"RSVD12 ",
	"INVALID"
};
#define SIZEOF_CONST_STR	sizeof(strConst)/sizeof(strConst[0])

static const char *strTMode[] =
{
	"2K     ",
	"8K     ",
	"4K     ",
	"1K     ",
	"16K    ",
	"32K    ",
	"RSVD1  ",
	"RSVD2  ",
	"INVALID"
};
#define SIZEOF_TMODE_STR	sizeof(strTMode)/sizeof(strTMode[0])

static const char *strPilot[] =
{
	"PP1    ",
	"PP2    ",
	"PP3    ",
	"PP4    ",
	"PP5    ",
	"PP6    ",
	"PP7    ",
	"PP8    ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"RSVD5  ",
	"RSVD6  ",
	"RSVD7  ",
	"RSVD8  ",
	"INVALID"
};
#define SIZEOF_PILOT_STR	sizeof(strPilot)/sizeof(strPilot[0])

static const char *strPARP[] =
{
	"NONE   ",
	"ACE    ",
	"TR     ",
	"TR/ACE ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"RSVD5  ",
	"RSVD6  ",
	"RSVD7  ",
	"RSVD8  ",
	"RSVD9  ",
	"RSVD10 ",
	"RSVD11 ",
	"RSVD12 ",
	"INVALID"
};
#define SIZEOF_PARP_STR	sizeof(strPARP)/sizeof(strPARP[0])

static const char *strCodeRate[] =
{
	"1/2    ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"INVALID"
};
#define SIZEOF_CODERATE_STR	sizeof(strCodeRate)/sizeof(strCodeRate[0])

static const char *strFEC[] =
{
	"LDPC16K",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"INVALID"
};
#define SIZEOF_FEC_STR	sizeof(strFEC)/sizeof(strFEC[0])

static const char *strPLPType[] =
{
	"COMMON ",
	"DATA1  ",
	"DATA2  ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"RSVD5  ",
	"INVALID"
};
#define SIZEOF_PLPTYPE_STR	sizeof(strPLPType)/sizeof(strPLPType[0])

static const char *strPLPPayLoad[] =
{
	"GFPS   ",
	"GCS    ",
	"GSE    ",
	"TS     ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"RSVD5  ",
	"RSVD6  ",
	"RSVD7  ",
	"RSVD8  ",
	"RSVD9  ",
	"RSVD10 ",
	"RSVD11 ",
	"RSVD12 ",
	"RSVD13 ",
	"RSVD14 ",
	"RSVD15 ",
	"RSVD16 ",
	"RSVD17 ",
	"RSVD18 ",
	"RSVD19 ",
	"RSVD20 ",
	"RSVD21 ",
	"RSVD22 ",
	"RSVD23 ",
	"RSVD24 ",
	"RSVD25 ",
	"RSVD26 ",
	"RSVD27 ",
	"RSVD28 ",
	"INVALID"
};
#define SIZEOF_PLPPAYLOAD_STR	sizeof(strPLPPayLoad)/sizeof(strPLPPayLoad[0])

static const char *strPLPConstel[] =
{
	"QPSK   ",
	"QAM16  ",
	"QAM64  ",
	"QAM256 ",
	"RSVD1  ",
	"RSVD2  ",
	"RSVD3  ",
	"RSVD4  ",
	"INVALID"
};
#define SIZEOF_PLPCONSTEL_STR	sizeof(strPLPConstel)/sizeof(strPLPConstel[0])

static const char *strPLPCodeRate[] =
{
	"1/2    ",
	"3/5    ",
	"2/3    ",
	"3/4    ",
	"4/5    ",
	"5/6    ",
	"RSVD1  ",
	"RSVD2  ",
	"INVALID"
};
#define SIZEOF_PLPCODERATE_STR	sizeof(strPLPCodeRate)/sizeof(strPLPCodeRate[0])

static const char *strPLPFEC[] =
{
	"LDPC16K",
	"LDPC64K",
	"RSVD1  ",
	"RSVD2  ",
	"INVALID"
};
#define SIZEOF_PLPFEC_STR	sizeof(strPLPFEC)/sizeof(strPLPFEC[0])

/**********************************************************************************************************/
// functions

// Set the DVB-C AnnexA tuner
BOOL SetTunDVBT2(CATBoardTunDVBT2 *pATBoardCtrl, STunDVBT2Opt Options)
{
	char TmpStr[MAX_TMP_STR_LEN];

	Message(E_VERBOSE_2, "*****************************************************************");
	Message(E_VERBOSE_2, "Initializing Tuner....");
	// initialize the tuner
	if (!pATBoardCtrl->Init())
		return FALSE;
	Message(E_VERBOSE_2, "Initializing Tuner Done");

	Message(E_VERBOSE_2, "Set tuner....");
	// set the tuner
	if (!pATBoardCtrl->Set(Options.m_nFrequency, Options.m_BandWidth, Options.m_nPLPId))
		return FALSE;

	// give the tuner some time to lock.
	SysSleep(1000);
	Message(E_VERBOSE_2, "Set tuner Done");

	// print settings
	switch(Options.m_BandWidth)
	{
	case BANDWIDTH_8_7_MHZ:
		Message(E_VERBOSE_2, "Bandwidth: 8MHz");
		break;
	case BANDWIDTH_7_6_MHZ:
		Message(E_VERBOSE_2, "Bandwidth: 7MHz");
		break;
	case BANDWIDTH_6_MHZ:
		Message(E_VERBOSE_2, "Bandwidth: 6MHz");
		break;
	case BANDWIDTH_5_MHZ:
		Message(E_VERBOSE_2, "Bandwidth: 5MHz");
		break;
	default:
		Message(E_VERBOSE_2, "Bandwidth: NOT SUPPORTED");
		break;
	}

	Message(E_VERBOSE_2, "Settings:");
	sprintf(TmpStr, "Frequency: %ld Hz", Options.m_nFrequency);
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "PLP ID: %d", Options.m_nPLPId);
	Message(E_VERBOSE_2, TmpStr);

	BOOL bInSync;
	BOOL bLock;
	s32 nSnr;
	u32 nBer;
	src_spectral_inversion_t Inversion;

	// get status
	if (!pATBoardCtrl->GetStatus(bInSync, bLock, Inversion, nSnr, nBer))
	{
		Message(E_VERBOSE_2, "Device not locked");
		return FALSE;
	}

	// print status
	Message(E_VERBOSE_2, "Status:");
	sprintf(TmpStr, "Lock detected: %s", bLock ? "YES" : "NO");
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "In sync: %s", bInSync ? "YES" : "NO");
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "Spectral inversion: %s", Inversion == INVERSION_OFF ? "OFF" : "ON");
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "Signal to noise ratio: %.1f dB", (double)nSnr/1000.0);
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "Bit error rate: %ld bit/s", nBer);
	Message(E_VERBOSE_2, TmpStr);

	// L1Pre status
	sony_dvb_dvbt2_l1pre_t L1Pre;
	if (!pATBoardCtrl->GetL1PreStatus(L1Pre))
		return FALSE;

	Message(E_VERBOSE_2, "L1PRE Status:");
	if (L1Pre.mod > SIZEOF_CONST_STR)
		L1Pre.mod = (sony_dvb_dvbt2_l1post_constell_t)(SIZEOF_CONST_STR-1);
	sprintf(TmpStr, "Modulation: %s", strConst[L1Pre.mod]);
	Message(E_VERBOSE_2, TmpStr);
	if (L1Pre.cr > SIZEOF_CODERATE_STR)
		L1Pre.cr = (sony_dvb_dvbt2_l1post_cr_t)(SIZEOF_CODERATE_STR-1);
	sprintf(TmpStr, "Code rate: %s", strCodeRate[L1Pre.cr]);
	Message(E_VERBOSE_2, TmpStr);
	if (L1Pre.fec > SIZEOF_FEC_STR)
		L1Pre.fec = (sony_dvb_dvbt2_l1post_fec_type_t)(SIZEOF_FEC_STR-1);
	sprintf(TmpStr, "FEC: %s", strFEC[L1Pre.fec]);
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "Cell ID: %d", L1Pre.cellId);
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "Netword ID: %d", L1Pre.networkId);
	Message(E_VERBOSE_2, TmpStr);
	sprintf(TmpStr, "System ID: %d", L1Pre.systemId);
	Message(E_VERBOSE_2, TmpStr);

	// L1Pre status (not used yet)
	sony_dvb_dvbt2_l1post_t L1PostInfo;
	if (!pATBoardCtrl->GetL1PostStatus(L1PostInfo))
		return FALSE;

	// Get tuner info
	sony_dvb_demod_t2_preset_t PresetInfo;
	if (!pATBoardCtrl->GetTuneInfo(PresetInfo))
		return FALSE;
	
	Message(E_VERBOSE_2, "Tuner info:");
	if (PresetInfo.gi > SIZEOF_GUARD_STR)
		PresetInfo.gi = (sony_dvb_dvbt2_guard_t)(SIZEOF_GUARD_STR-1);
	sprintf(TmpStr, "Guard interval: %s", strGuard[PresetInfo.gi]);
	Message(E_VERBOSE_2, TmpStr);
	if (PresetInfo.mode > SIZEOF_TMODE_STR)
		PresetInfo.mode = (sony_dvb_dvbt2_mode_t)(SIZEOF_TMODE_STR-1);
	sprintf(TmpStr, "Transmission mode: %s", strTMode[PresetInfo.mode]);
	Message(E_VERBOSE_2, TmpStr);
	if (PresetInfo.pp > SIZEOF_PILOT_STR)
		PresetInfo.pp = (sony_dvb_dvbt2_pp_t)(SIZEOF_PILOT_STR-1);
	sprintf(TmpStr, "Pilot mode: %s", strPilot[PresetInfo.pp]);
	Message(E_VERBOSE_2, TmpStr);
	if (PresetInfo.papr > SIZEOF_PARP_STR)
		PresetInfo.papr = (sony_dvb_dvbt2_papr_t)(SIZEOF_PARP_STR-1);
	sprintf(TmpStr, "PARP mode: %s", strPARP[PresetInfo.papr]);
	Message(E_VERBOSE_2, TmpStr);

	// Get PLP info
	sony_dvb_dvbt2_plp_info_t PLPInfo;
	if (!pATBoardCtrl->GetPLPInfo(PLPInfo))
		return FALSE;
	Message(E_VERBOSE_2, "PLP ID's:");
	// IDs:
	for (int nIdx = 0; nIdx < PLPInfo.NumPLPs; nIdx++)
	{
		sprintf(TmpStr, "PLP[%d]: ID: %d", nIdx, PLPInfo.PLPIds[nIdx]);
		Message(E_VERBOSE_2, TmpStr);
	}

	sprintf(TmpStr, "PLP info of ID: %d", Options.m_nPLPId);
	Message(E_VERBOSE_2, TmpStr);
	if (PLPInfo.PLPInfo.type > SIZEOF_PLPTYPE_STR)			// Type	
		PLPInfo.PLPInfo.type = (sony_dvb_dvbt2_plp_type_t)(SIZEOF_PLPTYPE_STR-1);
	sprintf(TmpStr, "PLP Type: %s", strPLPType[PLPInfo.PLPInfo.type]);
	Message(E_VERBOSE_2, TmpStr);

	if (PLPInfo.PLPInfo.payload > SIZEOF_PLPPAYLOAD_STR)			// Payload
		PLPInfo.PLPInfo.payload = (sony_dvb_dvbt2_plp_payload_t)(SIZEOF_PLPPAYLOAD_STR-1);
	sprintf(TmpStr, "PLP Payload mode: %s", strPLPPayLoad[PLPInfo.PLPInfo.payload]);
	Message(E_VERBOSE_2, TmpStr);

	if (PLPInfo.PLPInfo.constell > SIZEOF_PLPCONSTEL_STR)			// constel
		PLPInfo.PLPInfo.constell = (sony_dvb_dvbt2_plp_constell_t)(SIZEOF_PLPCONSTEL_STR-1);
	sprintf(TmpStr, "PLP Modulation: %s", strPLPConstel[PLPInfo.PLPInfo.constell]);
	Message(E_VERBOSE_2, TmpStr);

	if (PLPInfo.PLPInfo.plpCr > SIZEOF_PLPCODERATE_STR)			// Code Rate
		PLPInfo.PLPInfo.plpCr = (sony_dvb_dvbt2_plp_code_rate_t)(SIZEOF_PLPCODERATE_STR-1);
	sprintf(TmpStr, "PLP Code rate: %s", strPLPCodeRate[PLPInfo.PLPInfo.plpCr]);
	Message(E_VERBOSE_2, TmpStr);

	if (PLPInfo.PLPInfo.fec > SIZEOF_PLPFEC_STR)			// FEC
		PLPInfo.PLPInfo.fec = (sony_dvb_dvbt2_plp_fec_t)(SIZEOF_PLPFEC_STR-1);
	sprintf(TmpStr, "PLP Fec: %s", strPLPFEC[PLPInfo.PLPInfo.fec]);
	Message(E_VERBOSE_2, TmpStr);

	return TRUE;
}
