#include <applications/dialog/Dialog.h>
#include <ADuCM360.h>
#include <hal/timer.h>
#include <applications/message.h>

void encoder_open(void)
{
	pADI_GP1->GPCON = (pADI_GP1->GPCON & ~GP1CON_CON1_MSK) | GP1CON_CON1_GPIOIRQ4;
	pADI_GP1->GPCON = (pADI_GP1->GPCON & ~GP1CON_CON5_MSK) | GP1CON_CON5_GPIOIRQ5;
	pADI_GP1->GPCON = (pADI_GP1->GPCON & ~GP1CON_CON7_MSK) | GP1CON_CON7_GPIOIRQ7;

	GP1OCE_OCE1_BBA = false;
	GP1OCE_OCE5_BBA = false;
	GP1OCE_OCE7_BBA = false;

	GP1PUL_PUL1_BBA = true;
	GP1PUL_PUL5_BBA = true;
	GP1PUL_PUL7_BBA = true;

	GP1OEN_OEN1_BBA = false;
	GP1OEN_OEN5_BBA = false;
	GP1OEN_OEN7_BBA = false;

	pADI_INTERRUPT->EI1CFG = (pADI_INTERRUPT->EI1CFG & ~EI1CFG_IRQ4MDE_MSK) | EI1CFG_IRQ4MDE_RISEORFALL;
	pADI_INTERRUPT->EI1CFG = (pADI_INTERRUPT->EI1CFG & ~EI1CFG_IRQ5MDE_MSK) | EI1CFG_IRQ5MDE_RISEORFALL;
	pADI_INTERRUPT->EI1CFG = (pADI_INTERRUPT->EI1CFG & ~EI1CFG_IRQ7MDE_MSK) | EI1CFG_IRQ7MDE_RISEORFALL;

	EI1CFG_IRQ4EN_BBA = true;
	EI1CFG_IRQ5EN_BBA = true;
	EI1CFG_IRQ7EN_BBA = true;

	NVIC_SetPriority(EINT4_IRQn, NVIC_EncodePriority(6, 1, 2));
	NVIC_SetPriority(EINT5_IRQn, NVIC_EncodePriority(6, 1, 2));
	NVIC_SetPriority(EINT7_IRQn, NVIC_EncodePriority(6, 1, 2));

	NVIC_EnableIRQ(EINT4_IRQn);
	NVIC_EnableIRQ(EINT5_IRQn);
	NVIC_EnableIRQ(EINT7_IRQn);
}

static int debounce(int argc, char *argv[])
{
	app msg;
	msg.argc = 0;
	msg.argv = new char*;

	if (GP1IN_IN7_BBA)
	{
		msg.fun = on_button_up;
	}
	else
	{

		msg.fun = on_button_down;
	}

	post_message(msg);

	EI1CFG_IRQ7EN_BBA = true;
}

static int on_int7(int argc, char *argv[])
{
	timer t;
	t.time = 50;
	t.timer_app.argc = 0;
	t.timer_app.fun = debounce;
	t.timer_app.argv = new char*;

	new_timer(t);
}

#ifdef __cplusplus
extern "C"
{
#endif
	static int in1, in5, count;

	void Ext_Int4_Handler(void) //encoder
	{
		EI1CFG_IRQ4EN_BBA = false;

		if (count < 3)
		{
			++count;
		}
		else
		{
			count = 0;

			app msg;
			msg.argc = 0;

			if (GP1IN_IN5_BBA == in1)
			{
				msg.fun = on_cw;
			}
			else
			{
				msg.fun = on_ccw;
			}

			ts_post_message(msg);
		}

		in5 = GP1IN_IN5_BBA;

		EICLR_IRQ4_BBA = true;
		EI1CFG_IRQ5EN_BBA = true;
		__DSB();
	}

	void Ext_Int5_Handler(void) //encoder
	{
		EI1CFG_IRQ5EN_BBA = false;

		if (count < 3)
		{
			++count;
		}
		else
		{
			count = 0;

			app msg;
			msg.argc = 0;

			if (GP1IN_IN1_BBA == in5)
			{
				msg.fun = on_ccw;
			}
			else
			{
				msg.fun = on_cw;
			}

			ts_post_message(msg);
		}

		in1 = GP1IN_IN1_BBA;

		EICLR_IRQ5_BBA = true;
		EI1CFG_IRQ4EN_BBA = true;
		__DSB();
	}

	void Ext_Int7_Handler(void) //encoder button
	{
		EI1CFG_IRQ7EN_BBA = false;

		app msg;
		msg.argc = 0;
		msg.fun = on_int7;

		ts_post_message(msg);

		EICLR_IRQ7_BBA = true;
		__DSB();
	}
#ifdef __cplusplus
}
#endif
