//
#include "descriptors.h"
#include "SPI_lib.h"

#ifndef EIC_lib
#define EIC_lib

#define KEYPAD_BACKSPACE 42
#define KEYPAD_NUMLOCK 83
#define KEYPAD_DIVIDE 84
#define KEYPAD_MULTIPLY 85
#define KEYPAD_MINUS 86
#define KEYPAD_PLUS 87
#define KEYPAD_ENTER 88
#define KEYPAD_1 89
#define KEYPAD_2 90
#define KEYPAD_3 91
#define KEYPAD_4 92
#define KEYPAD_5 93
#define KEYPAD_6 94
#define KEYPAD_7 95
#define KEYPAD_8 96
#define KEYPAD_9 97
#define KEYPAD_0 98
#define KEYPAD_DEL 99



volatile uint8_t keyStatus = 0x0F;	//0 - not pressed		1 - pressed
volatile uint8_t currentKeyStatus = 0x0F;
volatile uint16_t statusChangeCount[4];

volatile uint32_t extIntFlag;
volatile uint32_t portAInReg;
volatile uint32_t portBInReg;
volatile uint32_t pinValue;
volatile uint16_t timerCount;
volatile uint32_t currentVals;

extern USB_EndpointData EP1IN;
extern volatile uint8_t keyChangeFlag;
extern volatile uint8_t patternChangeFlag;
extern volatile uint8_t intensityChangeFlag;


volatile uint8_t lastBitFlag = 0xFF;
volatile uint8_t keyboardCommandActive = 0;

void IO_init_EIC(void){
	//EIC
	PORT->Group[0].DIRCLR.reg = (PORT_PA00);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[0].bit.PMUXE = 0x0;
	PORT->Group[0].PINCFG[0].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA01);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[0].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[1].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA02);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[1].bit.PMUXE = 0x0;
	PORT->Group[0].PINCFG[2].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA17);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[8].bit.PMUXO = 0x8;
	PORT->Group[0].PINCFG[17].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA18);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[9].bit.PMUXE = 0x8;		//LUT 0x8
	PORT->Group[0].PINCFG[18].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA19);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[9].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[19].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA20);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[10].bit.PMUXE = 0x0;
	PORT->Group[0].PINCFG[20].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA21);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[10].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[21].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA10);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[5].bit.PMUXE = 0x0;
	PORT->Group[0].PINCFG[10].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA11);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[5].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[11].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA12);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[6].bit.PMUXE = 0x0;
	PORT->Group[0].PINCFG[12].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA13);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[6].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[13].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRCLR.reg = (PORT_PA27);	//DIRECTION - INPUT
	PORT->Group[0].PMUX[13].bit.PMUXO = 0x0;
	PORT->Group[0].PINCFG[27].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[1].DIRCLR.reg = (PORT_PB11);	//DIRECTION - INPUT
	PORT->Group[1].DIRCLR.reg = (PORT_PB10);	//DIRECTION - INPUT
	PORT->Group[1].PMUX[5].bit.PMUXE = 0x8;
	PORT->Group[1].PINCFG[10].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
		
	PORT->Group[1].DIRCLR.reg = (PORT_PB22);	//DIRECTION - INPUT
	PORT->Group[1].PMUX[11].bit.PMUXE = 0x0;
	PORT->Group[1].PINCFG[22].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN	//
	
	PORT->Group[1].DIRCLR.reg = (PORT_PB23);	//DIRECTION - INPUT
	PORT->Group[1].PMUX[11].bit.PMUXO = 0x0;
	PORT->Group[1].PINCFG[23].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[1].DIRCLR.reg = (PORT_PB08);	//DIRECTION - INPUT
	PORT->Group[1].PMUX[4].bit.PMUXE = 0x0;
	PORT->Group[1].PINCFG[8].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[1].DIRCLR.reg = (PORT_PB09);	//DIRECTION - INPUT
	PORT->Group[1].PMUX[4].bit.PMUXO = 0x0;
	PORT->Group[1].PINCFG[9].reg = 0x03;	// - DRVSTR - - - PULLEN - INEN - PMUXEN
	
	PORT->Group[0].DIRSET.reg = PORT_PA07;
	PORT->Group[0].OUTCLR.reg = PORT_PA07;
}



void EIC_init(void){
	MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC;
	//Enable GCLK for TCC0 and link it to GCLK0 see "PCHCTRLm Mapping" from product datasheet
	GCLK->PCHCTRL[3].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(0));
	EIC->CTRLA.bit.CKSEL = 0;
	
	while(EIC->SYNCBUSY.bit.ENABLE);
	EIC->CTRLA.bit.ENABLE = 0;
	while(EIC->SYNCBUSY.bit.ENABLE);
	

	EIC->CONFIG[0].bit.SENSE0 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE1 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE2 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE3 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE4 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE5 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE6 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[0].bit.SENSE7 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	
	EIC->CONFIG[1].bit.SENSE0 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE1 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE2 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE3 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE4 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE5 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	EIC->CONFIG[1].bit.SENSE7 = 0x03;	//0x0 NONE - RISE - FALL - BOTH - HIGH - LOW
	
	EIC->INTENSET.bit.EXTINT = 0xBFFF;
	//EIC->EVCTRL.bit.EXTINTEO = 0x0004;
	
	NVIC_EnableIRQ(3);
	
	while(EIC->SYNCBUSY.bit.ENABLE);
	EIC->CTRLA.bit.ENABLE = 1;
	while(EIC->SYNCBUSY.bit.ENABLE);
}

void bufferAdd(uint8_t key){
	for(int i = 0; i < 8; i++){
		if(EP1IN.u8[i] == 0) {
			EP1IN.u8[i] = key;
			return;
		}
	}
}

void bufferRemove(uint8_t key){
	for(int i = 0; i < 8; i++){
		if(EP1IN.u8[i] == key) {
			EP1IN.u8[i] = 0;
			return;
		}
	}
}

void EIC_Handler(){
	extIntFlag = EIC->INTFLAG.reg;
	
	//if(isPatternActive == 0) SPI_playPattern(SPI_pattern);
	//else SPI_stopPattern();
	
	portAInReg = PORT->Group[0].IN.reg;
	portBInReg = PORT->Group[1].IN.reg;
	
	//PA00 - +
	if(extIntFlag & (1 << 0)) {
		if(portAInReg & PORT_PA00) bufferRemove(KEYPAD_PLUS);	
		else bufferAdd(KEYPAD_PLUS);
		keyChangeFlag = 1;
	}
													
	//PA01					
	if(extIntFlag & (1 << 1)) {
		if(portAInReg & PORT_PA01) bufferRemove(KEYPAD_3);
		else bufferAdd(KEYPAD_3);
		keyChangeFlag = 1;
	}
	
	//PA02 - 6
	if(extIntFlag & (1 << 2)) {
		if(portAInReg & PORT_PA02) {
			bufferRemove(KEYPAD_6);
		} else {
			if (keyboardCommandActive == 0){
				bufferAdd(KEYPAD_6);
			} else {
				patternChangeFlag = 3;
			}	 
		}
		keyChangeFlag = 1;
	}
						
	//PA19					
	if(extIntFlag & (1 << 3)) {
			if(portAInReg & PORT_PA19) {
				bufferRemove(KEYPAD_2);
			} else {
				if (keyboardCommandActive == 0){
					bufferAdd(KEYPAD_2);
				} else {
					if(intensityExp > 1) {
						intensityChangeFlag = 1;
						intensityExp--;
					}
				}	 
			}
			keyChangeFlag = 1;
	}
	
	//PA20
	if(extIntFlag & (1 << 4)) {
		if(portAInReg & PORT_PA20) bufferRemove(KEYPAD_1);
		else bufferAdd(KEYPAD_1);
		keyChangeFlag = 1;
	}
						
	//PA21
	if(extIntFlag & (1 << 5)) {
		if(portAInReg & PORT_PA21) bufferRemove(KEYPAD_DEL);
		else bufferAdd(KEYPAD_DEL);
		keyChangeFlag = 1;
	}
	
	//PB22	
	if(extIntFlag & (1 << 6)) {
		if(portBInReg & PORT_PB22) bufferRemove(KEYPAD_0);
		else bufferAdd(KEYPAD_0);
		keyChangeFlag = 1;
	}
					
	//PB23 - -					
	if(extIntFlag & (1 << 7)) {
		if(portBInReg & PORT_PB23) bufferRemove(KEYPAD_MINUS);
		else bufferAdd(KEYPAD_MINUS);
		keyChangeFlag = 1;
	}
	
	//PB08 - 9
	if(extIntFlag & (1 << 8)) {
		if(portBInReg & PORT_PB08) bufferRemove(KEYPAD_9);
		else bufferAdd(KEYPAD_9);
		keyChangeFlag = 1;
	}
	
	//PA10 - 5
	if(extIntFlag & (1 << 10)) {
		if(portAInReg & PORT_PA10) {
			bufferRemove(KEYPAD_5);
			keyboardCommandActive = 0;
		} else {
			bufferAdd(KEYPAD_5);
			keyboardCommandActive = 1;
		}
		keyChangeFlag = 1;	
	}
	
	//PB09 - 4
	if(extIntFlag & (1 << 9)) {
		if(portBInReg & PORT_PB09) {
			bufferRemove(KEYPAD_4);
		} else {
			if (keyboardCommandActive == 0){
				bufferAdd(KEYPAD_4);
			} else {
				patternChangeFlag = 1;
			}	 
		}
		keyChangeFlag = 1;
	}
							
	//PA11 - *
	if(extIntFlag & (1 << 11)) {
		if(portAInReg & PORT_PA11) bufferRemove(KEYPAD_MULTIPLY);
		else bufferAdd(KEYPAD_MULTIPLY);
		keyChangeFlag = 1;
	}
	
	//PA12 - 7
	if(extIntFlag & (1 << 12)) {
		if(portAInReg & PORT_PA12) bufferRemove(KEYPAD_7);
		else bufferAdd(KEYPAD_7);

		keyChangeFlag = 1;
	}
	
	//PA13 - 8
	if(extIntFlag & (1 << 13)) {
		if(portAInReg & PORT_PA13) {
				bufferRemove(KEYPAD_8);
			} else {
				if (keyboardCommandActive == 0){
					bufferAdd(KEYPAD_8);
				} else {
					if(intensityExp < 7) {
						intensityChangeFlag = 1;
						intensityExp++;
					}
				}	 
			}
			keyChangeFlag = 1;		
	}
	
	//PA27 - ENTER
	if(extIntFlag & (1 << 15)) {
		if(portAInReg & PORT_PA27) bufferRemove(KEYPAD_ENTER);
		else bufferAdd(KEYPAD_ENTER);
		keyChangeFlag = 1;
	}
		
	EIC->INTFLAG.reg |= extIntFlag;
}


void LUT_setting(){
	// - Enable TCC0 Bus clock (Timer counter control clock)
	MCLK->APBDMASK.reg |= MCLK_APBDMASK_EVSYS;
	// 5 - EVSYSCHANNEL 0
	GCLK->PCHCTRL[5].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(0));
	
	CCL->LUTCTRL[0].bit.ENABLE = 0;
	CCL->LUTCTRL[0].bit.INSEL0 = 0x0;
	CCL->LUTCTRL[0].bit.INSEL1 = 0x4;
	CCL->LUTCTRL[0].bit.INSEL2 = 0x4;
	CCL->LUTCTRL[0].bit.TRUTH = 0x3C;	// 1 XOR 2
	CCL->LUTCTRL[0].bit.LUTEO = 1;
	CCL->LUTCTRL[0].bit.ENABLE = 1;
	
	GCLK->PCHCTRL[6].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(0));
	
	CCL->LUTCTRL[1].bit.ENABLE = 0;
	CCL->LUTCTRL[1].bit.INSEL0 = 0x0;
	CCL->LUTCTRL[1].bit.INSEL1 = 0x0;
	CCL->LUTCTRL[1].bit.INSEL2 = 0x4;
	CCL->LUTCTRL[1].bit.TRUTH = 0xF0;	// 2
	CCL->LUTCTRL[1].bit.LUTEO = 1;
	CCL->LUTCTRL[1].bit.ENABLE = 1;
	
	CCL->CTRL.bit.ENABLE = 1;
	
	EVSYS->USER[26].bit.CHANNEL = 0x01;
	EVSYS->CHANNEL[0].bit.EVGEN = 0x4E;
	EVSYS->CHANNEL[0].bit.EDGSEL = 0x3;
	EVSYS->CHANNEL[0].bit.PATH = EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
	
	EVSYS->USER[27].bit.CHANNEL = 0x02;
	EVSYS->CHANNEL[1].bit.EVGEN = 0x4F;
	EVSYS->CHANNEL[1].bit.EDGSEL = 0x3;
	EVSYS->CHANNEL[1].bit.PATH = EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
}

void TC0_init(){
	// - Enable TCC0 Bus clock (Timer counter control clock)
	MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0;
	//Enable GCLK for TCC0 and link it to GCLK0 see "PCHCTRLm Mapping" from product datasheet
	GCLK->PCHCTRL[27].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(4));		//16M
	// - Disable TC0
	while(TC0->COUNT8.SYNCBUSY.bit.ENABLE);
	TC0->COUNT8.CTRLA.bit.ENABLE = 0;
	while(TC0->COUNT8.SYNCBUSY.bit.ENABLE);
	
	TC0->COUNT8.EVCTRL.bit.EVACT = 0x1;
	
	TC0->COUNT8.EVCTRL.bit.TCEI = 1;
	
	TC0->COUNT8.CTRLA.bit.MODE = 0x1;	// 16 - 8 - 32
	TC0->COUNT8.CTRLBSET.bit.ONESHOT = 1;
	TC0->COUNT8.CTRLA.bit.PRESCALER = 0x0; //0x4 16 0x5 64 0x6 256
	TC0->COUNT8.INTENSET.bit.OVF = 1;
	TC0->COUNT8.PER.reg = 0;

	NVIC_EnableIRQ(TC0_IRQn);
	
	while(TC0->COUNT8.SYNCBUSY.bit.ENABLE);
	TC0->COUNT8.CTRLA.bit.ENABLE = 1;
	while(TC0->COUNT8.SYNCBUSY.bit.ENABLE);
	
	//PORT->Group[0].DIRSET.reg = PORT_PA18;
}
void TC0_Handler(){	
	//PB11 - 5
	if(PORT->Group[0].IN.reg & PORT_PA17) {
		if (lastBitFlag & 1) {
			if (PORT->Group[0].IN.reg & PORT_PA18){
				bufferRemove(KEYPAD_BACKSPACE);
				
				lastBitFlag |= 2;
			} else {
				bufferAdd(KEYPAD_BACKSPACE);
				lastBitFlag &= 1;
			}
		}
	}
	
	if(PORT->Group[0].IN.reg & PORT_PA18) {
		if (lastBitFlag & 2) {
			if (PORT->Group[0].IN.reg & PORT_PA17){
				bufferRemove(KEYPAD_DIVIDE);
				lastBitFlag |= 1;
				} else {
				bufferAdd(KEYPAD_DIVIDE);
				lastBitFlag &= 2;
			}
		}
	}
	
	keyChangeFlag = 1;
	
	TC0->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF;
}

void TC1_init(){
	// - Enable TCC0 Bus clock (Timer counter control clock)
	MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC1;
	//Enable GCLK for TCC0 and link it to GCLK0 see "PCHCTRLm Mapping" from product datasheet
	GCLK->PCHCTRL[27].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(4));		//16M
	// - Disable TC1
	while(TC1->COUNT8.SYNCBUSY.bit.ENABLE);
	TC1->COUNT8.CTRLA.bit.ENABLE = 0;
	while(TC1->COUNT8.SYNCBUSY.bit.ENABLE);
	
	TC1->COUNT8.EVCTRL.bit.EVACT = 0x1;
	
	TC1->COUNT8.EVCTRL.bit.TCEI = 1;
	
	TC1->COUNT8.CTRLA.bit.MODE = 0x1;	// 16 - 8 - 32
	TC1->COUNT8.CTRLBSET.bit.ONESHOT = 1;
	TC1->COUNT8.CTRLA.bit.PRESCALER = 0x0; //0x4 16 0x5 64 0x6 256
	TC1->COUNT8.INTENSET.bit.OVF = 1;
	TC1->COUNT8.PER.reg = 0;

	NVIC_EnableIRQ(TC1_IRQn);
	
	
	
	while(TC1->COUNT8.SYNCBUSY.bit.ENABLE);
	TC1->COUNT8.CTRLA.bit.ENABLE = 1;
	while(TC1->COUNT8.SYNCBUSY.bit.ENABLE);
	
	//PORT->Group[0].DIRSET.reg = PORT_PA18;
}
void TC1_Handler(){
	//PB11 - 5
	if(PORT->Group[1].IN.reg & PORT_PB10) bufferRemove(KEYPAD_NUMLOCK);
	else bufferAdd(KEYPAD_NUMLOCK);
	keyChangeFlag = 1;
	
	TC1->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF;
}

void initKeyboardISR(){
	IO_init_EIC();
	EIC_init();
	LUT_setting();
	TC0_init();
	TC1_init();
}
#endif