#include "CSC5262.h"

#include <stdio.h>
#include "../hubolib.h"

using namespace BCM2835;
using namespace HuboLib;


CSC5262::CSC5262(int pulseLength, int pin, bool bQuiet)
{
	m_PulseLength 	= pulseLength;
	m_Pin 			= pin;
	m_bQuiet 		= bQuiet;
	
	if (!IsGPIOInitialized() && !m_bQuiet)
		printf ("GPIO not properly initialized - following calls will fail!");

	FunctionSelectPin(m_Pin, Output);
}


CSC5262::~CSC5262()
{
}


void CSC5262::SendPysicalBit (CSC5262::TriSTateBit bit)
{
	switch (bit)
	{
	case Zero:
		// 1000
		SetPin(m_Pin);		Delay_MicroSeconds(m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(3*m_PulseLength);
		// 1000
		SetPin(m_Pin);		Delay_MicroSeconds(m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(3*m_PulseLength);
		break;

	case One:
		// 1110
		SetPin(m_Pin);		Delay_MicroSeconds(3*m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(m_PulseLength);
		// 1110
		SetPin(m_Pin);		Delay_MicroSeconds(3*m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(m_PulseLength);
		break;

	case Floating:
		// 1000
		SetPin(m_Pin);		Delay_MicroSeconds(m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(3*m_PulseLength);
		// 1110
		SetPin(m_Pin);		Delay_MicroSeconds(3*m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(m_PulseLength);
		break;

	case Sync:
		// 1000 0000	0000 0000 	0000 0000	0000 0000
		SetPin(m_Pin);		Delay_MicroSeconds(m_PulseLength);
		ClearPin(m_Pin);	Delay_MicroSeconds(31*m_PulseLength);
		break;

	}
}


void CSC5262::SendLogicalBit (unsigned short bit)
{
	if (bit)
		SendPysicalBit(Zero);
	else
		SendPysicalBit(Floating);
}


void CSC5262::SendCommand (bool bTurnOn)
{
	if (bTurnOn)
	{
		SendPysicalBit (Zero);
		SendPysicalBit (Floating);
	}
	else
	{
		SendPysicalBit (Floating);
		SendPysicalBit (Zero);
	}
}

void CSC5262::SendSync ()
{
	SendPysicalBit (Sync);
}


bool CSC5262::Switch (unsigned char SystemCode, unsigned char Receiver, bool bTurnOn)
{
	unsigned long long 	start = GetTime_MicroSeconds ();

	// Clock out system code first...
	for (int rover = 0x10; rover > 0; rover >>= 1)
		SendLogicalBit (SystemCode & rover);

	// ...add socket address...
	for (int rover = 0x10; rover > 0; rover >>= 1)
		SendLogicalBit (Receiver & rover);

	// ... append command...
	SendCommand (bTurnOn);

	// ... and finally send sync frame.
	SendSync ();

	unsigned long long 	stop = GetTime_MicroSeconds ();

	// The datagram has an overall length of 128 bits.
	// We regard the datagram to be transmitted correct if we see the transmission time to not exceed the time by more than the time of 1 pulse length.
	bool bSuccess = ( ((long) (stop-start)) <= (128L + 1L)*m_PulseLength );

	if (!m_bQuiet)
		printf ("Duration = %llu micro seconds - %s\n", stop-start, bSuccess?"ok":"failed");

	return bSuccess;
}

bool CSC5262::SwitchSocket (unsigned char SystemCode, unsigned char Receiver, bool bTurnOn, int repeatedSuccess, int totalTransmittion)
{
	if (repeatedSuccess > totalTransmittion)
	{
		if (!m_bQuiet)
			printf ("User error - The number of total transmissions must not be less than the number of successfully repeated transmissions.\n");
		return false;
	}
	if (repeatedSuccess < 3)
	{
		if (!m_bQuiet)
			printf ("User error - The number of successfully repeated transmissions must at least be 3 in order to switch the socket.\n");
		return false;
	}

	int transmissionCount = 0;
	int successCount = 0;
	while (1)
	{
		if (Switch (SystemCode, Receiver, bTurnOn))
			successCount++;
		else
			successCount = 0;

		if (successCount == repeatedSuccess)
			return true;

		transmissionCount++;

		if (transmissionCount == totalTransmittion)
			return false;
	}
}
