/* PS2 keyboard */
/* dalinai vogtas is interneto */

/* ************************************************************************
** modifikuotas STM32F1xx cube 
** Naudoja alias: PS2_DATA_GPIO_Port, PS2_DATA_Pin , PS2_CLK_Pin .
** Reikelaingas pertraukimas H->L and CLK, kuris kviecia ps2interrupt();
**
** (copyleft) 2020 http://www.vabolis.lt
*************************************************************************** */
#define PS2BUFFER_SIZE 16
static volatile uint8_t PS2buffer[PS2BUFFER_SIZE];
static volatile uint8_t head, tail;



// mini Amstrad klavietura -> ASCII
const unsigned char amstrad[] = {
0,
0, // 1
0, // 2
'j', // 3 - j
0, // 4
'b', // 5 - b
0, // 6 - ADDRESS BOOK
0, // 7
0, // 8
0, // 9 - CURSOR RIGHT
0, // a
'v', // b - v
0, // c
'u', // d - u
'i', // e - i
0, // f
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15 - FAX
0, // 16 - CURSOR LEFT
0, // 17
0, // 18
0, // 19
0, // 1a - MOBILE
'5', // 1b - 5
0, // 1c - EMAIL
'6', // 1d - 6
'7', // 1e - 7
0, // 1f
0, // 20
'q', // 21 - q
'4', // 22 - 4
'w', // 23 - w
'e', // 24 - e
0, // 25
'r', // 26 - r
0, // 27
0, // 28
'g', // 29 - g
0, // 2a - SMS
0, // 2b
'\n', // 2c - ENTER
0, // 2d
0, // 2e - CURSOR DOWN
0, // 2f
0, // 30
'a', // 31 - a
'o', // 32 - o
's', // 33 - s
'p', // 34 - p
'd', // 35 - d
'f', // 36 - f
0, // 37
0, // 38
0, // 39
'l', // 3a - l
'\\', // 3b - \'
0, // 3c - LSHIFT
'z', // 3d - z
0, // 3e - CURSOR UP
0, // 3f
0, // 40
'n', // 41 - n
'm', // 42 - m
'?', // 43 - .?/
':', // 44 - ;:
0, // 45
0, // 46 - SERVICES
0, // 47
0, // 48
0, // 49 - SYMBOL
0, // 4a
' ', // 4b - SPACE
0, // 4c
0, // 4d
'x', // 4e - x
0, // 4f
0, // 50
0, // 51
't', // 52 - t
0, // 53
'c', // 54 - c
0, // 55 - RIGHT SHIFT
0, // 56
0, // 57
0, // 58
0, // 59
0, // 5a
'h', // 5b - h
0, // 5c
'y', // 5d - y
0, // 5e
0, // 5f
0, // 60
0, // 61
0, // 62
0, // 63
0, // 64
0, // 65
0, // 66
0, // 67
0, // 68
0, // 69 - OFFICE
0, // 6a
'3', // 6b - 3
127, // 6c - del
0, // 6d
0, // 6e
0, // 6f
0, // 70 - STORE
27, // 71 - Esc / STOP
0, // 72 - HOME
'2', // 73 - 2
'1', // 74 - 1
'0', // 75 - 0
'k', // 76 - k
0, // 77 - INTERNET
0, // 78
'8', // 79 - 8
0, // 7a - SETUP
0, // 7b
0, // 7c - GAMES
'9', // 7d - 9
0, // 7e
0, // 7f
0, // 80
0, // 81
0, // 82
0, // 83 - PRINT
0
};

unsigned char scan_decode(unsigned char i)
{
return amstrad[i];
}


void ps2interrupt(void)
{
uint32_t now_ms;
static uint8_t bitcount=0;
static uint8_t incoming=0;
static uint32_t prev_ms=0;
static uint8_t parity;
//uint8_t n;
uint8_t val;

	if( HAL_GPIO_ReadPin(PS2_DATA_GPIO_Port, PS2_DATA_Pin)) val=1; else val=0;


now_ms = HAL_GetTick();
	if (now_ms - prev_ms > 250) {
		bitcount = 0;
		incoming = 0;
	}

	prev_ms = now_ms;




bitcount++;         // Now point to next bit
    switch( bitcount )
       {
       case 1:  // Start bit
                incoming = 0;
                parity = 0;
                break;
       case 2:
       case 3:
       case 4:
       case 5:
       case 6:
       case 7:
       case 8:
       case 9:  // Data bits
                parity += val;        // another one received ?
                incoming >>= 1;       // right shift one place for next bit
                incoming |= ( val ) ? 0x80 : 0;    // or in MSbit
                break;
       case 10: // Parity check
                parity &= 1;          // Get LSB if 1 = odd number of 1's so parity should be 0
                if( parity == val )   // Both same parity error
                  parity = 0xFD;      // To ensure at next bit count clear and discard
                break;
       case 11: // Stop bit
                if( parity >= 0xFD )  // had parity error
                  {
                  // Should send resend byte command here currently discard
                  }
                else                  // Good so save byte in buffer
                  {
                  val = head + 1;
                  if( val >= PS2BUFFER_SIZE )
                    val = 0;
                  if( val != tail )
                    {
                    PS2buffer[ val ] = incoming;
                    head = val;
                    }
                  }
                // fall through to default
       default: // in case of weird error and end of byte reception re-sync
                bitcount = 0;
      }

























/* CIA KITAS VARIANTAS, irgi veikia.... */
	
/*	
	n = bitcount - 1;
	if (n <= 7) {incoming |= (val << n);}
	bitcount++;
	if (bitcount == 11) {
		uint8_t i = head + 1;
		if (i >= PS2BUFFER_SIZE) i = 0;
		if (i != tail) {PS2buffer[i] = incoming; head = i;}
		bitcount = 0;
		incoming = 0;
	}
*/	
}

uint8_t get_PS2scan_code(void)
{
	uint8_t c, i;

	i = tail;
	if (i == head) return 0;
	i++;
	if (i >= PS2BUFFER_SIZE) i = 0;
	c = PS2buffer[i];
	tail = i;
	return c;
}


