Files
x1key/keyconv.c
Philip Smart 6ac7fa5563 First push
2022-02-17 13:17:58 +00:00

244 lines
6.8 KiB
C

/*
Connect a PS / 2 keyboard to SHARP X1
Key code conversion process
Created on July 23, 2014
Kyoichi Sato http://kyoutan.jpn.org/
There is no guarantee.
The part created by Kyoichi Sato has no restrictions on its use. You can use it freely regardless of whether it is commercial or non-commercial.
It means that you can copy, modify, distribute, or sell it without permission.
No need to contact.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "sfr_r8m12a.h"
#include "keyconv.h"
#include "iodefine.h"
#include "keytable.h"
#include "ps2.h"
#include "x1key.h"
volatile unsigned short x1shift = 0xFF; // Valid at X1 shift state save 0
#define TENKEY ((unsigned char) (1 << 7))
#define PRESS ((unsigned char) (1 << 6))
#define REPEAT ((unsigned char) (1 << 5))
#define GRAPH ((unsigned char) (1 << 4))
#define CAPS ((unsigned char) (1 << 3))
#define KANA ((unsigned char) (1 << 2))
#define SHIFT ((unsigned char) (1 << 1))
#define CTRL ((unsigned char) (1 << 0))
volatile unsigned char ps2ex = 0; // PS2 keyboard extended key flag
#define EXKEY ((unsigned char) (1 << 0))
#define RELEASE ((unsigned char) (1 << 1))
#define PAUSE_BREAK ((unsigned char) (1 << 2))
unsigned char codeconv(unsigned char data);
unsigned char checkbreak(void);
unsigned char x1code(unsigned char data);
void x1trans(unsigned char data);
void keyconv(void)
{
unsigned char data;
data = ps2get (); // Wait until it is received from the PS / 2 keyboard and read 1 byte
switch (data)
{
case 0xE0: // Extended key
ps2ex |= EXKEY; // Extended key flag set
break;
case 0xF0: // separated
ps2ex |= RELEASE; // Separated flag set
break;
default:
// Convert PS / 2 code to internal code
if (0xE1 == data) data = checkbreak (); // PAUSE / BREAK key determination
if (0 == (ps2ex & EXKEY))
{// normal key
if (0x8F <data) data = 0x00;
data = KEY106 [data];
}
else
{// Extended key
if (0x5F <data) data = KEY106 [data + 0x30];
else data = KEY106 [data];
}
ps2ex &= ~EXKEY; // Extended key flag reset
x1trans (x1code (data)); // Convert internal code to X1 code and send
break;
}
}
// Convert from internal code to X1 code
unsigned char x1code(unsigned char data)
{
x1shift |= TENKEY; // Special key flag reset
// Check if it is a special key such as numeric keypad or function key SHIFT CTRL
if (((0x3A <data) && (0x59> data)) || (0x5A <data)) x1shift &= ~TENKEY; // Special key flag set
switch (data) // branch by internal code
{
case GRAPH_CODE1:
case GRAPH_CODE2:
if (0 == (ps2ex & RELEASE)) x1shift &= ~GRAPH; // Pressed
else x1shift |= GRAPH; // separated
data = 0;
break;
case CAPS_CODE:
if (0 != (ps2ex & RELEASE)) x1shift = (x1shift | CAPS) & (~(x1shift & CAPS)); // Toggle every time you release
data = 0;
break;
case KANA_CODE:
if (0 != (ps2ex & RELEASE)) x1shift = (x1shift | KANA) & (~ (x1shift & KANA)); // Toggle every time you release
data = 0;
break;
case SHIFTL_CODE:
case SHIFTR_CODE:
if (0 == (ps2ex & RELEASE)) x1shift &= ~SHIFT; // Pressed
else x1shift |= SHIFT; // separated
data = 0;
break;
case CTRL_CODE:
if (0 == (ps2ex & RELEASE)) x1shift &= ~CTRL; // Pressed
else x1shift |= CTRL; // released
data = 0;
break;
case UP_CODE:
data = 0x1E;
break;
case DOWN_CODE:
data = 0x1F;
break;
case LEFT_CODE:
data = 0x1D;
break;
case RIGHT_CODE:
data = 0x1C;
break;
case INS_CODE:
data = 0x12;
break;
case DEL_CODE: // BS is usually in the key table
data = 0x08;
break;
case HOME_CODE:
x1shift &= ~SHIFT; // + SHIFT
data = 0x0B;
break;
default: // Convert from normal key internal code to X1 code
data = codeconv (data);
break;
}
return data;
}
// The PAUSE / BREAK key starts with an unusual code, so it can be determined by another process.
unsigned char checkbreak(void)
{
unsigned char a;
for (a = 1; a <8; a++)
{
if (ps2get () != BREAK_CODE [a]) break;
}
if (8 == a) // BREAK key
{
ps2ex |= PAUSE_BREAK;
return 0x80;
}
return 0x00; // wasn't the BREAK key
}
// Send to X1
void x1trans(unsigned char data)
{
static unsigned char lastshift = 0xFF;
if (0 == (ps2ex & RELEASE))
{ // pushed
x1shift &= ~PRESS;
// Send when it is not zero and when the shift state changes
if ((0x00 != data) || (x1shift != lastshift)) X1_send (((unsigned short) x1shift << 8) | data);
if (0 != (ps2ex & PAUSE_BREAK)) // Send the release code when PAUSE / BREAK
{
x1shift |= TENKEY; // Clear special key flag
X1_send (((unsigned short) x1shift << 8) | 0x00);
ps2ex &= ~PAUSE_BREAK;
}
}
else
{// separated
x1shift |= PRESS;
X1_send (((unsigned short) x1shift << 8) | 0x00);
ps2ex &= ~RELEASE; // Clear the released flag
if (0x0B == data) x1shift |= SHIFT; // At HOME -SHIFT
}
lastshift = x1shift;
}
unsigned char codeconv(unsigned char data)
{
unsigned char status;
status = (x1shift & (CAPS | GRAPH | KANA | SHIFT | CTRL));
if ((KANA | GRAPH | SHIFT | CTRL) == status) // CAPS
{
unsigned char ret;
ret = CHR_TBL0 [data];
if ((0x60 <ret) && (0x7b> ret)) ret -= 0x20; // Uppercase alphabet
return ret;
}
if ((KANA | GRAPH | CTRL) == status) // CAPS + SHIFT
{
unsigned char ret;
ret = CHR_TBL1 [data];
if ((0x40 <ret) && (0x5b> ret)) ret += 0x20; // In lowercase letters
return ret;
}
status &= (GRAPH | KANA | SHIFT | CTRL);
if ((GRAPH | KANA | CTRL) == status) return CHR_TBL1 [data]; // SHIFT
if ((GRAPH | KANA | SHIFT) == status) return CHR_TBL3 [data]; // CTRL
if ((KANA | SHIFT | CTRL) == status) return CHR_TBL2 [data]; // GRAPH
if ((SHIFT | CTRL) == status) return CHR_TBL2 [data]; // GRAPH + KANA
if ((GRAPH | SHIFT | CTRL) == status) return CHR_TBL4 [data]; // KANA
if ((GRAPH | CTRL) == status) return CHR_TBL5 [data]; // KANA + SHIFT
return CHR_TBL0 [data]; // No shift
}
#ifdef __cplusplus
}
#endif