Files
mips/src/libsys/mips_ps2.c
T
jens cf233c4d81 - fixed bootloader
- bootloader added board file
- refactored header files
- constify constants

git-svn-id: http://moon:8086/svn/mips@99 a8ebac50-d88d-4704-bea3-6648445a41b3
2017-01-18 22:28:07 +00:00

473 lines
10 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "libsys.h"
#include "mips_ps2.h"
uint32_t ps2_readchar(ps2_if_t *pIF);
const ps2_if_t ps2_if[2] =
{
{ps2_type_unknown, (uint32_t*)SYS_PS2_0_STAT, (uint32_t*)SYS_PS2_0_DATA},
{ps2_type_unknown, (uint32_t*)SYS_PS2_1_STAT, (uint32_t*)SYS_PS2_1_DATA}
};
uint32_t PS2_get_num_if(void)
{
return (sizeof(ps2_if)/sizeof(ps2_if_t));
}
int PS2_readchar(void const *pInst)
{
assert(pInst);
ps2_if_t *pIF = (ps2_if_t*)pInst;
return (int)ps2_readchar(pIF);
}
void PS2_open(void const *pInst)
{
assert(pInst);
ps2_if_t *pIF = (ps2_if_t*)pInst;
PS2_init(pIF);
}
void PS2_close(void const *pInst)
{
}
void PS2_byte_write(ps2_if_t *pIF, uint8_t byte)
{
assert(pIF);
while(!(*pIF->pCTRL & SYS_PS2_BIT_TX_EMPTY));
*pIF->pDATA = (uint32_t)byte;
}
uint32_t PS2_byte_read(ps2_if_t *pIF, uint32_t timeout_ms)
{
assert(pIF);
while(!(*pIF->pCTRL & SYS_PS2_BIT_RX_AVAIL))
{
timeout_ms--;
if (!timeout_ms)
return PS2_ERR_TIMEOUT;
sleep(1);
}
return (uint32_t)*pIF->pDATA;
}
uint32_t PS2_cmd(ps2_if_t *pIF, uint8_t cmd, uint32_t ack_timeout_ms)
{
uint32_t result;
PS2_byte_write(pIF, cmd);
result = PS2_byte_read(pIF, ack_timeout_ms);
if (0xFA != result)
{
printf ("PS2_cmd(%p): no ACK received. Result = %08X\n", pIF->pCTRL, result);
return PS2_ERR_PS2_PREFIX | result;
}
return 0;
}
void PS2_flush(ps2_if_t *pIF)
{
while (!IS_ERROR(PS2_byte_read(pIF, 10)));
}
uint32_t PS2_init(ps2_if_t *pIF)
{
int i;
uint8_t id[2];
pIF->type = ps2_type_unknown;
uint32_t result;
// Disable RX-interrupt
*pIF->pCTRL &= ~SYS_PS2_BIT_RX_INTEN;
printf ("PS2_init(%p) - Initialize... ", pIF->pCTRL);
// Flush buffer
PS2_flush(pIF);
// send RESET
result = PS2_cmd(pIF, 0xFF, 1000);
if (IS_ERROR(result))
{
printf ("Reset error %08X\n", result);
return result;
}
// Read BAT
result = PS2_byte_read(pIF, 1000);
if (0xAA != result)
{
printf ("BAT error %08X\n", result);
return result;
}
printf ("Success\n");
while(1)
{
// Read ID
result = PS2_byte_read(pIF, 10);
if (IS_ERROR(result))
{
// No ID => keyboard
printf ("PS2_init(%p) - Keyboard detected\n", pIF->pCTRL);
// send Get Device-ID
result = PS2_cmd(pIF, 0xF2, 1000);
if (IS_ERROR(result))
{
printf ("Get Device-ID error %08X\n", result);
break;
}
id[0] = PS2_byte_read(pIF, 1000);
id[1] = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Device-ID: %02X%02X\n", pIF->pCTRL, id[0], id[1]);
// Get Scan code set (phase 1)
result = PS2_cmd(pIF, 0xF0, 1000);
if (IS_ERROR(result))
{
printf ("1. Get Scan code error %08X\n", result);
break;
}
// Get Scan code set (phase 2)
result = PS2_cmd(pIF, 0x00, 1000);
if (IS_ERROR(result))
{
printf ("2. Get Scan code error %08X\n", result);
break;
}
result = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Current scan code set = %d\n", pIF->pCTRL, result);
// if Scan code SET != 2
if (result != 2)
{
printf ("PS2_init(%p) - Set scan code set = 2\n", pIF->pCTRL);
// Set Scan code set (phase 1)
result = PS2_cmd(pIF, 0xF0, 1000);
if (IS_ERROR(result))
{
printf ("1. Set Scan code error %08X\n", result);
break;
}
// Set Scan code set (phase 2)
result = PS2_cmd(pIF, 0x02, 1000);
if (IS_ERROR(result))
{
printf ("2. Set Scan code error %08X\n", result);
break;
}
}
// Test LEDs
for (i=0; i < 4; i++)
{
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x02, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x04, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x01, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
}
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x00, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
pIF->type = ps2_type_keyb;
result = pIF->type;
break;
}
// We got a byte => maybe mouse
if (result == 0)
{
// We got zero => yes, it's a mouse
printf ("PS2_init(%p) - Mouse device detected\n", pIF->pCTRL);
// send Get Device-ID
result = PS2_cmd(pIF, 0xF2, 1000);
if (IS_ERROR(result))
{
printf ("Get Device-ID error %08X\n", result);
break;
}
id[0] = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Device-ID: %02X\n", pIF->pCTRL, id[0]);
printf ("PS2_init(%p) - Enable stream mode...", pIF->pCTRL);
result = PS2_cmd(pIF, 0xF4, 1000);
if (IS_ERROR(result))
{
printf ("error %08X\n", result);
break;
}
printf ("Success\n");
pIF->type = ps2_type_mouse;
result = pIF->type;
break;
}
}
// Flush buffer
PS2_flush(pIF);
if (IS_ERROR(result))
return result;
// Enable RX-interrupt
*pIF->pCTRL |= SYS_PS2_BIT_RX_INTEN;
return result;
}
// -------------------------------------------------------------
// BEGIN QUICK AND DIRTY
// -------------------------------------------------------------
//keymap for the AT keyboard SG layout
typedef struct
{
uint8_t scancode;
uint8_t unshifted;
uint8_t shifted;
uint8_t altered;
} libsys_key_entry_t;
#define SHIFTED (1<<0)
#define ALTERED (1<<1)
#define CONTROLLED (1<<2)
static const libsys_key_entry_t __keymap_german[] =
{
{0x1c, 'a', 'A', 'a'},
{0x32, 'b', 'B', 'b'},
{0x21, 'c', 'C', 'c'},
{0x23, 'd', 'D', 'd'},
{0x24, 'e', 'E', '€'},
{0x2b, 'f', 'F', 'f'},
{0x34, 'g', 'G', 'g'},
{0x33, 'h', 'H', 'h'},
{0x43, 'i', 'I', 'i'},
{0x3b, 'j', 'J', 'j'},
{0x42, 'k', 'K', 'k'},
{0x4b, 'l', 'L', 'l'},
{0x3a, 'm', 'M', 'µ'},
{0x31, 'n', 'N', 'n'},
{0x44, 'o', 'O', 'o'},
{0x4d, 'p', 'P', 'p'},
{0x15, 'q', 'Q', '@'},
{0x2d, 'r', 'R', 'r'},
{0x1b, 's', 'S', 's'},
{0x2c, 't', 'T', 't'},
{0x3c, 'u', 'U', 'u'},
{0x2a, 'v', 'V', 'v'},
{0x1d, 'w', 'W', 'w'},
{0x22, 'x', 'X', 'x'},
{0x1a, 'y', 'Y', 'y'},
{0x35, 'z', 'Z', 'z'},
{0x16, '1', '!', '1'},
{0x1e, '2', '"', '2'},
{0x26, '3', '§', '3'},
{0x25, '4', '$', '4'},
{0x2e, '5', '%', '5'},
{0x36, '6', '&', '6'},
{0x3d, '7', '/', '{'},
{0x3e, '8', '(', '['},
{0x46, '9', ')', ']'},
{0x45, '0', '=', '}'},
{0x4e, 'ß', '?', '\\'},
{0x29, ' ', ' ', ' '},
{0x41, ',', ';', ','},
{0x49, '.', ':', '.'},
{0x4a, '-', '_', '-'},
{0x52, 'ä', 'Ä', 'ä'},
{0x4c, 'ö', 'Ö', 'ö'},
{0x54, 'ü', 'Ü', 'ü'},
{0x5a, '\n', '\n', '\n'}, //RETURN
{0x5b, '+', '*', '~'},
{0x5d, '#', '\'', '#'},
{0x0e, '^', '°', '^'},
{0x61, '<', '>', '|'},
{0x66, '\b', '\b', '\b'},
{0} //sentinel
};
static char __findkey(char scancode, int mode)
{
const libsys_key_entry_t *p = __keymap_german;
while (p->scancode)
{
if (p->scancode == scancode)
{
switch (mode)
{
case SHIFTED:
return p->shifted;
case ALTERED:
return p->altered;
case ALTERED|SHIFTED:
default:
return p->unshifted;
}
}
p++;
}
return 0;
}
#define RELEASE 0x8000
#define SPECIALKEY 0x4000
#define EXTENDED 0x2000
#define X_CONTROLLED 0x0400
#define X_ALTERED 0x0200
#define X_SHIFTED 0x0100
#define CAPS (SPECIALKEY|0x58)
#define F1 (SPECIALKEY|0x05)
#define F2 (SPECIALKEY|0x06)
#define F3 (SPECIALKEY|0x04)
#define F4 (SPECIALKEY|0x0c)
#define F5 (SPECIALKEY|0x03)
#define F6 (SPECIALKEY|0x0b)
#define F7 (SPECIALKEY|0x83)
#define F8 (SPECIALKEY|0x0a)
#define F9 (SPECIALKEY|0x01)
#define F10 (SPECIALKEY|0x09)
#define F11 (SPECIALKEY|0x78)
#define F12 (SPECIALKEY|0x07)
#define ARROW_UP (SPECIALKEY|EXTENDED|0x75)
#define ARROW_DOWN (SPECIALKEY|EXTENDED|0x72)
#define ARROW_LEFT (SPECIALKEY|EXTENDED|0x6b)
#define ARROW_RIGHT (SPECIALKEY|EXTENDED|0x74)
uint32_t ps2_readchar(ps2_if_t *pIF)
{
uint8_t c;
static char mode = 0;
static char nextrelease = 0;
static char extended = 0;
int flags = 0;
int char_valid = 0;
uint8_t key;
while (!(SYS_PS2_BIT_RX_AVAIL & *pIF->pCTRL));
key = *pIF->pDATA & 0xFF;
switch (key)
{
case 0xf0: //release key
nextrelease = 1;
break;
case 0x14: //control key
if (nextrelease)
{
mode &= ~CONTROLLED;
} else
{
mode |= CONTROLLED;
}
nextrelease = 0;
break;
case 0x12: //left SHIFT
case 0x59: //right SHIFT
if (nextrelease)
{
mode &= ~SHIFTED;
} else
{
mode |= SHIFTED;
}
nextrelease = 0;
break;
case 0x11: //left and right ALT (right one also with E0)
if (nextrelease)
{
mode &= ~ALTERED;
} else
{
mode |= ALTERED;
}
nextrelease = 0;
break;
case 0xe0: //extended key following
extended = 1;
break;
default:
if (nextrelease) flags |= RELEASE;
if (extended) flags |= EXTENDED;
flags |= mode << 8;
c = __findkey(key, mode);
char_valid = (c && ((flags & RELEASE) != RELEASE));
nextrelease = 0;
extended = 0;
break;
}
if (char_valid)
{
// fprintf(stderr, "c = %c (%d), flags = 0x%08X, mode = 0x%08X\n", c, c, flags, mode);
return c;
}
return -1;
}
// -------------------------------------------------------------
// END QUICK AND DIRTY
// -------------------------------------------------------------