/*
 * TLA2528.cpp
 *
 *  Created on: May 21, 2025
 *      Author: User
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

#include "TLA2528.h"

TLA2528::TLA2528(const char *pDevName, alt_u32 nDeviceAddr) {
	// TODO Auto-generated constructor stub
	strcpy(m_szDevName, pDevName);
	m_nDeviceAddr = nDeviceAddr;
}

TLA2528::~TLA2528() {
	// TODO Auto-generated destructor stub
}

bool TLA2528::Read(alt_u8 *pBuf, int nReadLen){
	bool bSuccess;
	int i;;

	bSuccess = Open(m_szDevName, m_nDeviceAddr);


	if (!bSuccess){
		printf("Failed to open %s (Device Address 0x%02x).", m_szDevName, m_nDeviceAddr);
	}else{
		for(i=0;i<nReadLen && bSuccess;i++){
//			bSuccess = ReadReg8(i, pBuf+i);
			bSuccess = Addr8_ReadReg8(i, pBuf+i);

		}
	}


	Close();


	return bSuccess;
}

bool TLA2528::ShowInfo(void){
	bool bSuccess;
	uint8_t szBuf[0x3D];
	uint8_t CTL_1_MODE, CTL_2_MODE, CTL_3_MODE;


	bSuccess = Read(szBuf, sizeof(szBuf));
	if (bSuccess){
		// decode. refer to https://www.ti.com/lit/ds/symlink/tfp410.pdf?ts=1747834921804&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTFP410
		printf("VEN_ID:0x%02x%02x (expected 0x014C)\r\n", szBuf[1], szBuf[0]);
		printf("DEV_ID:0x%02x%02x (expected 0x0410)\r\n", szBuf[3], szBuf[2]);
		printf("REV_ID:0x%02x (expected 0x00)\r\n", szBuf[4]);

		CTL_1_MODE = szBuf[8];
		CTL_2_MODE = szBuf[9];
		CTL_3_MODE = szBuf[10];

		printf("CTL_1_MODE: 0x%02x (default 0xBE)\r\n", CTL_1_MODE);
		printf("\tPD#=%d, %s\r\n", (CTL_1_MODE & 0x01)?1:0,(CTL_1_MODE & 0x01)?"Normal operation":"Power down");
		printf("\tEDGE=%d, input data latched to the %s edge of IDCK+\r\n", (CTL_1_MODE & 0x02)?1:0,(CTL_1_MODE & 0x02)?"rising":"falling");
		printf("\tBSEL=%d, %s\r\n", (CTL_1_MODE & 0x04)?1:0,(CTL_1_MODE & 0x04)?"24-bit operation with single-edge clock":"12-bit operation with dual-edge clock");
		printf("\tDSEL=%d, clock mode: %s\r\n", (CTL_1_MODE & 0x08)?1:0,(CTL_1_MODE & 0x08)?"Differential":"single-ended");
		printf("\tHEN=%d, HSYNC input is transmitted %s\r\n", (CTL_1_MODE & 0x10)?1:0,(CTL_1_MODE & 0x10)?"in tis original state":"as a fixed low");
		printf("\tVEN=%d, VSYNC input is transmitted %s\r\n", (CTL_1_MODE & 0x20)?1:0,(CTL_1_MODE & 0x20)?"in tis original state":"as a fixed low");
		printf("\tTDIS=%d, T.M.D.S circuitry %s\r\n", (CTL_1_MODE & 0x40)?1:0,(CTL_1_MODE & 0x40)?"is disabled":"enable state is determined by PHD");

		printf("CTL_2_MODE: 0x%02x (default 0x00)\r\n", CTL_2_MODE);
		printf("\tMDI=%d, %s\r\n", (CTL_2_MODE & 0x01)?1:0,(CTL_2_MODE & 0x01)?"Logic Level remains the same":"Detected logic level change in detection signal");
		printf("\tHTPLG=%d, %s level detected on the EDGE/HTPLG pin (pin 9)\r\n", (CTL_2_MODE & 0x02)?1:0,(CTL_2_MODE & 0x02)?"High":"Low");
		printf("\tRSEN=%d, A powered-on receiver is %s\r\n", (CTL_2_MODE & 0x04)?1:0,(CTL_2_MODE & 0x04)?"detected":"not detected");
		printf("\tTSEL=%d, Interrupt bit (MDI) is generated by monitoring %s\r\n", (CTL_2_MODE & 0x10)?1:0,(CTL_2_MODE & 0x10)?"HTPLG":"RSEN");
		printf("\tMSEL[3:1]=%d\r\n", (CTL_2_MODE >> 4) ^ 0x07);
		printf("\tVLOW=%d, the VREF analog input selects %s-swing inputs\r\n", (CTL_2_MODE & 0x80)?1:0,(CTL_2_MODE & 0x80)?"high":"low");

		printf("CTL_3_MODE: 0x%02x (default 0x80)\r\n", CTL_3_MODE);
		printf("\tCTL[2:1]=%d\r\n", (CTL_3_MODE >> 1) & 0x03);
		printf("\tDKEN=%d, Data de-skew is %s\r\n", (CTL_3_MODE & 0x10)?1:0,(CTL_3_MODE & 0x10)?"enabled":"disabled");
		printf("\tDK[3:1]=%d\r\n", (CTL_3_MODE >> 5) & 0x07);


	}else{
		printf("failed to read registers.\r\n");
	}


	return bSuccess;
}

bool TLA2528::IsHTPLG(void){
	bool bSuccess;
	bool bIsHTPLG = false;
	uint8_t value8;


	bSuccess = Open(m_szDevName, m_nDeviceAddr);


	if (bSuccess){
			bSuccess = Addr8_ReadReg8(9, &value8);
			if (bSuccess && (value8 & 0x02))
				bIsHTPLG = true;
	}


	Close();

	return bIsHTPLG;

}



bool TLA2528::PowerOn(bool bTrunOn){
	bool bSuccess;
	uint8_t value8;

	bSuccess = Open(m_szDevName, m_nDeviceAddr);

	if (bSuccess)
		bSuccess = Addr8_ReadReg8(0x08, &value8);
	if (bSuccess){
		if (bTrunOn)
			value8 |= 0x01;
		else
			value8 &= 0xFE;

		bSuccess = Addr8_WriteReg8(0x08, value8);
	}


	Close();

	return bSuccess;
}

bool TLA2528::Write_Reg(alt_u8 nRegAddr, alt_u8 nValue){
	bool bSuccess;
	alt_u16 Addr16;

	//bool WriteReg8(alt_u16 nRegByteOffset, alt_u8 nValue8);
	Addr16 = OP_REG_WRITE;
	Addr16 <<= 8;
	Addr16 |= nRegAddr;
	bSuccess = WriteReg8(Addr16, nValue);

	return bSuccess;

}

bool TLA2528::Read_Reg(alt_u8 nRegAddr, alt_u8 *pnRead8){
	bool bSuccess;
	alt_u16 Addr16;

	//bool ReadReg8(alt_u16 nRegByteOffset, alt_u8 *pnRead8);
	Addr16 = OP_REG_READ;
	Addr16 <<= 8;
	Addr16 |= nRegAddr;
	bSuccess = ReadReg8(Addr16, pnRead8);

	return bSuccess;

}

bool TLA2528::Read_Data16(alt_u16 *pnRead16){
	bool bSuccess;
	bSuccess = ReadData(2, pnRead16);
	return bSuccess;
}


bool TLA2528::Read_8CH_ManualMode(uint16_t szCH[8], bool bShowData){
	int ch;
	alt_u16 value16;
	bool bSuccess = true;

	bSuccess = Write_Reg(REG_SEQUENCE_CFG, 0x00); // set manual mode


	for(ch=0;ch<8 && bSuccess;ch++){

		//////////////////
		// Write Register to select channel
		bSuccess = Write_Reg(REG_CHANNEL_SEL, ch);

		// conversion time 600 ns
		//////////////////
		// read data
		if (bSuccess){
			usleep(1);
			bSuccess = Read_Data16(&value16); // this is previous channel value
			usleep(1);
			bSuccess = Read_Data16(&value16); // second cyclone is the expected channel. see figure 31 in datasheet
			// decode data output (see datasheet figure 25 SPI Frames for reading data)
			if (bSuccess){
				szCH[ch] = value16;

				if (bShowData)
					printf("read ch%d = %04xh\r\n", ch, value16);
			}
		}

	} // for

	return bSuccess;



}
