#include <stdio.h>
#include <string>
#include <unistd.h>

#include "../hubolib.h"

using namespace HuboLib;
using namespace BCM2835;


/*
Compile and link:
	g++ SFKS2B1.cpp -L../ -lhubo -lpthread -lrt -o SFKS2B1.out
Run:
	sudo ./SFKS2B1.out
Purpose:
	The demo rings the SilverCrest SFKS2B1 433MHz door bell.
*/


const char* g_pCode = "ADCBADADADCBCBCBADADADADADADCBCBCBCBADADCEADCE"; 

class CCode
{
	public :
		CCode (unsigned short time, unsigned char signal)
		{
			m_time = time;
			m_signal = signal;
		}
			
	public :
		unsigned short m_time;
		unsigned char  m_signal;
};


CCode A( 365, 1);
CCode B( 385, 0);
CCode C(1095, 1);
CCode D(1120, 0);
CCode E(4405, 0);


void SendDatagram (unsigned short pin);
void BoostThreadPriority();


int main(int argc, char *argv[])
{
	if (!BCM2835::IsGPIOInitialized ())
	{
		printf ("GPIO not properly initialized. Are you running the program as sudoer?\n");
		return -1;
	}

	// Define the pin we will use for bit banging as output.
	unsigned short transmit_pin  = 17; // BCM GPIO=17 = GPIO0 = Raspi pinheader 11
	FunctionSelectPin(transmit_pin, Output);

	// Lift the priority of the thread in order to allow for a precise time keeping during bit banging.
	BoostThreadPriority();
	
	// The minimum of datagrams to repeat is around 2.
	// Let's send it 10 times to be on the save side.
	// The transmitter of the bell sends it around 100 times.
	for (int i=0; i<10; i++)
	{
		SendDatagram(transmit_pin);
	}

	return 0;
}


void SendDatagram (unsigned short pin)
{
	const char* pBuffer = g_pCode;
	while (*pBuffer)
	{
		switch (*pBuffer)
		{
			case 'A' : 	WritePin (pin, A.m_signal);
						Delay_MicroSeconds((unsigned long) A.m_time);
						break;
			case 'B' : 	WritePin (pin, B.m_signal);
						Delay_MicroSeconds((unsigned long) B.m_time);
						break;
			case 'C' : 	WritePin (pin, C.m_signal);
						Delay_MicroSeconds((unsigned long) C.m_time);
						break;
			case 'D' : 	WritePin (pin, D.m_signal);
						Delay_MicroSeconds((unsigned long) D.m_time);
						break;
			case 'E' : 	WritePin (pin, E.m_signal);
						Delay_MicroSeconds((unsigned long) E.m_time);
						break;
			default:
						printf ("Error - unknown code\n");
						return;
		}
		pBuffer++;
	}
}

#include <pthread.h>    
#include <assert.h>    
void BoostThreadPriority()
{
	// Scheduling params.
	sched_param param;
	int			policy;
	int			ret;
	pthread_t	threadHandle = pthread_self();

	// Get current scheduling parameters of thread.
	ret				= pthread_getschedparam (threadHandle, &policy, &param);
	assert (ret == 0);

	// Set scheduling parameters of thread to real time values (FIFO scheduling type and max prio).
	policy				 = SCHED_FIFO; // SCHED_RR;
	param.sched_priority = sched_get_priority_max(policy); // New max priority for new scheduling concept.
	ret					 = pthread_setschedparam(threadHandle, policy, &param);
	assert (ret == 0);
}


