
// ****************************************************************************
//
//                               Keys
//
// ****************************************************************************

#include "../include.h"

// last pressed key
volatile u8 KeyBuf = NOKEY;

// key pressed map
u8 KeyPressCnt[KEY_NUM];	// press counter
u8 KeyReleaseCnt[KEY_NUM];	// release counter
Bool KeyUseLong[KEY_NUM];	// flags - use long pressed key
Bool KeyLong[KEY_NUM];		// key is long pressed

const u8 KeyGpio[KEY_NUM] = {
	KEY_PREV_GPIO,		// key "Prev" GPIO
	KEY_NEXT_GPIO,		// key "Next" GPIO
	KEY_SLOW_GPIO,		// key "Slow" GPIO
	KEY_FAST_GPIO,		// key "Fast" GPIO
	KEY_HOLD_GPIO,		// key "Hold" GPIO
};

// get press button (NOKEY = no key)
u8 KeyGet()
{
	u8 key = KeyBuf;
	if (key != NOKEY) KeyBuf = NOKEY;
	return key;
}

// flush key buffer
void KeyFlush()
{
	KeyBuf = NOKEY;
}

// keyboard interrupt - called every 20ms from SysTick interrupt
void KeyScan()
{
	int i;
	Bool lng;

	// key loop
	for (i = 0; i < KEY_NUM; i++)
	{
		// key long mode
		lng = KeyUseLong[i];

		// check if key is pressed
		if (GPIO_In(KeyGpio[i]) == 0) // key is pressed
		{
			// start of press
			if (KeyReleaseCnt[i] == 0)
			{
				// reset flag of long press
				KeyLong[i] = False;

				// reset press counter
				KeyPressCnt[i] = 0;

				// store key code
				if (!lng) KeyBuf = i + KEY_FIRST;
			}

			// restart release counter
			KeyReleaseCnt[i] = 4;

			// increase press counter
			KeyPressCnt[i]++;

			// long press >= 500ms (1 step is 20ms)
			if (KeyPressCnt[i] == 25)
			{
				if (lng)
				{
					KeyBuf = KEY_FIRST_LONG + i;
					KeyLong[i] = True; // flag - long press
				}
				else
				{
					KeyBuf = i + 1;
					KeyPressCnt[i] = 25 - 8;
				}
			}

			// long press - repeat 1s
			if (KeyPressCnt[i] >= 50) KeyPressCnt[i] = 0;
		}

		// key is not pressed
		else
		{
			// decrease release counter
			if (KeyReleaseCnt[i] > 0)
			{
				KeyReleaseCnt[i]--;

				// short press
				if (lng && (KeyReleaseCnt[i] == 0) && !KeyLong[i])
				{
					KeyBuf = KEY_PREV + i;
				}
			}
		}
	}
}

// Initialize keyboard service
void KeyInit()
{
	int i;
	RCC_AFIClkEnable();
	RCC_PAClkEnable();
	RCC_PDClkEnable();
	for (i = 0; i < KEY_NUM; i++)
	{
		GPIO_Mode(KeyGpio[i], GPIO_MODE_IN_PU);
		KeyUseLong[i] = False;
	}
	KeyBuf = NOKEY;
}
