rewrite keyboard code

This commit is contained in:
Ash Wolf 2019-12-25 01:53:54 +00:00
parent 8f30d6fcef
commit 0b1051367a
7 changed files with 339 additions and 99 deletions

View File

@ -15,11 +15,12 @@ uint32_t Emulator::getRTC() {
}
uint32_t Emulator::readReg8(uint32_t reg) {
if (reg == PADR) {
return readKeyboard(kScan);
return ((portValues >> 24) & 0x80) | (readKeyboard() & 0x7F);
} else if (reg == PBDR) {
return (portValues >> 16) & 0xFF;
return ((portValues >> 16) & 0x0F) | (keyboardExtra << 4);
} else if (reg == PDDR) {
return (portValues >> 8) & 0xFF;
} else if (reg == PEDR) {
@ -467,4 +468,104 @@ void Emulator::diffPorts(uint32_t oldval, uint32_t newval) {
if (changes & 0x400000) log("PRT B6: %d", newval&0x400000);
if (changes & 0x800000) log("PRT B7: %d", newval&0x800000);
}
uint32_t Emulator::readKeyboard() const {
if (kScan & 8) {
// Select one keyboard
if ((kScan & 7) < 7)
return keyboardColumns[kScan & 7];
else
return 0;
} else if (kScan == 0) {
// Report all columns combined
uint8_t val = 0;
for (int i = 0; i < 7; i++)
val |= keyboardColumns[i];
return val;
} else {
return 0;
}
}
void Emulator::setKeyboardKey(EpocKey key, bool value) {
int idx = -1;
#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
switch ((int)key) {
case '1': KEY(0, 0);
case '2': KEY(1, 0);
case '3': KEY(2, 0);
case '4': KEY(3, 0);
case '5': KEY(4, 0);
case '6': KEY(5, 0);
case '7': KEY(6, 0);
case '8': KEY(0, 1);
case '9': KEY(1, 1);
case '0': KEY(2, 1);
case 'P': KEY(3, 1);
case EStdKeySingleQuote: KEY(4, 1);
case EStdKeyEnter: KEY(5, 1);
case EStdKeyBackspace: KEY(6, 1);
case EStdKeyEscape: KEY(0, 2);
case 'Q': KEY(1, 2);
case 'W': KEY(2, 2);
case 'E': KEY(3, 2);
case 'R': KEY(4, 2);
case 'T': KEY(5, 2);
case 'Y': KEY(6, 2);
case 'U': KEY(0, 3);
case 'J': KEY(1, 3);
case 'I': KEY(2, 3);
case 'K': KEY(3, 3);
case 'O': KEY(4, 3);
case 'L': KEY(5, 3);
case EStdKeyUpArrow: KEY(6, 3);
case EStdKeyTab: KEY(0, 4);
case 'A': KEY(1, 4);
case 'S': KEY(2, 4);
case 'D': KEY(3, 4);
case 'F': KEY(4, 4);
case 'G': KEY(5, 4);
case 'H': KEY(6, 4);
case EStdKeySpace: KEY(0, 5);
case EStdKeyComma: KEY(1, 5);
case 'M': KEY(2, 5);
case EStdKeyFullStop: KEY(3, 5);
case EStdKeyLeftArrow: KEY(4, 5);
case EStdKeyDownArrow: KEY(5, 5);
case EStdKeyRightArrow: KEY(6, 5);
case 'Z': KEY(0, 6);
case 'X': KEY(1, 6);
case EStdKeyMenu: KEY(2, 6);
case 'C': KEY(3, 6);
case 'V': KEY(4, 6);
case 'B': KEY(5, 6);
case 'N': KEY(6, 6);
case EStdKeyLeftShift: KEY(8, 0);
case EStdKeyRightShift: KEY(8, 1);
case EStdKeyLeftCtrl: KEY(8, 2);
case EStdKeyLeftFunc: KEY(8, 3);
}
if (idx >= 0x800) {
if (value)
keyboardExtra |= (idx & 0xFF);
else
keyboardExtra &= ~(idx & 0xFF);
} else if (idx >= 0) {
if (value)
keyboardColumns[idx >> 8] |= (idx & 0xFF);
else
keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
}
}
}

View File

@ -21,11 +21,14 @@ private:
uint32_t sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
uint32_t lcdControl = 0;
uint32_t lcdAddress = 0xC0000000;
uint32_t kScan = 0;
uint32_t rtc = 0;
uint32_t rtcDiv = 0;
uint64_t lcdPalette = 0;
uint32_t kScan = 0;
uint8_t keyboardColumns[7] = {0,0,0,0,0,0,0};
uint8_t keyboardExtra = 0;
Timer tc1, tc2;
CLPS7600 pcCardController;
bool halted = false, asleep = false;
@ -52,6 +55,7 @@ private:
void fetchProcessFilename(uint32_t obj, char *buf);
void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval);
uint32_t readKeyboard() const;
public:
Emulator();
@ -61,5 +65,6 @@ public:
int getLCDWidth() const override;
int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) const override;
void setKeyboardKey(EpocKey key, bool value) override;
};
}

View File

@ -1,19 +1 @@
#include "emubase.h"
uint8_t EmuBase::readKeyboard(int kScan) {
uint8_t val = 0;
if (kScan & 8) {
// Select one keyboard
int whichColumn = kScan & 7;
for (int i = 0; i < 7; i++)
if (keyboardKeys[whichColumn * 7 + i])
val |= (1 << i);
} else if (kScan == 0) {
// Report all columns combined
// EPOC's keyboard driver relies on this...
for (int i = 0; i < 8*7; i++)
if (keyboardKeys[i])
val |= (1 << (i % 7));
}
return val;
}

View File

@ -2,6 +2,104 @@
#include "arm710.h"
#include <unordered_set>
enum EpocKey {
EStdKeyDial = 161,
EStdKeyOff = 160,
EStdKeyHelp = 159,
EStdKeyDictaphoneRecord = 158,
EStdKeyDictaphoneStop = 157,
EStdKeyDictaphonePlay = 156,
EStdKeySliderUp = 155,
EStdKeySliderDown = 154,
EStdKeyDecContrast = 153,
EStdKeyIncContrast = 152,
EStdKeyBacklightToggle = 151,
EStdKeyBacklightOff = 150,
EStdKeyBacklightOn = 149,
EStdKeyMenu = 148,
EStdKeyNkpFullStop = 147,
EStdKeyNkp0 = 146,
EStdKeyNkp9 = 145,
EStdKeyNkp8 = 144,
EStdKeyNkp7 = 143,
EStdKeyNkp6 = 142,
EStdKeyNkp5 = 141,
EStdKeyNkp4 = 140,
EStdKeyNkp3 = 139,
EStdKeyNkp2 = 138,
EStdKeyNkp1 = 137,
EStdKeyNkpEnter = 136,
EStdKeyNkpPlus = 135,
EStdKeyNkpMinus = 134,
EStdKeyNkpAsterisk = 133,
EStdKeyNkpForwardSlash = 132,
EStdKeyEquals = 131,
EStdKeyMinus = 130,
EStdKeySquareBracketRight = 129,
EStdKeySquareBracketLeft = 128,
EStdKeyHash = 127,
EStdKeySingleQuote = 126,
EStdKeySemiColon = 125,
EStdKeyBackSlash = 124,
EStdKeyForwardSlash = 123,
EStdKeyFullStop = 122,
EStdKeyComma = 121,
EStdKeyXXX = 120,
EStdKeyF24 = 119,
EStdKeyF23 = 118,
EStdKeyF22 = 117,
EStdKeyF21 = 116,
EStdKeyF20 = 115,
EStdKeyF19 = 114,
EStdKeyF18 = 113,
EStdKeyF17 = 112,
EStdKeyF16 = 111,
EStdKeyF15 = 110,
EStdKeyF14 = 109,
EStdKeyF13 = 108,
EStdKeyF12 = 107,
EStdKeyF11 = 106,
EStdKeyF10 = 105,
EStdKeyF9 = 104,
EStdKeyF8 = 103,
EStdKeyF7 = 102,
EStdKeyF6 = 101,
EStdKeyF5 = 100,
EStdKeyF4 = 99,
EStdKeyF3 = 98,
EStdKeyF2 = 97,
EStdKeyF1 = 96,
EStdKeyScrollLock = 28,
EStdKeyNumLock = 27,
EStdKeyCapsLock = 26,
EStdKeyRightFunc = 25,
EStdKeyLeftFunc = 24,
EStdKeyRightCtrl = 23,
EStdKeyLeftCtrl = 22,
EStdKeyRightAlt = 21,
EStdKeyLeftAlt = 20,
EStdKeyRightShift = 19,
EStdKeyLeftShift = 18,
EStdKeyDownArrow = 17,
EStdKeyUpArrow = 16,
EStdKeyRightArrow = 15,
EStdKeyLeftArrow = 14,
EStdKeyDelete = 13,
EStdKeyInsert = 12,
EStdKeyPageDown = 11,
EStdKeyPageUp = 10,
EStdKeyEnd = 9,
EStdKeyHome = 8,
EStdKeyPause = 7,
EStdKeyPrintScreen = 6,
EStdKeySpace = 5,
EStdKeyEscape = 4,
EStdKeyEnter = 3,
EStdKeyTab = 2,
EStdKeyBackspace = 1,
EStdKeyNull = 0
};
class EmuBase : public ARM710
{
protected:
@ -19,10 +117,9 @@ public:
virtual int getLCDWidth() const = 0;
virtual int getLCDHeight() const = 0;
virtual void readLCDIntoBuffer(uint8_t **lines) const = 0;
virtual void setKeyboardKey(EpocKey key, bool value) = 0;
std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
uint64_t currentCycles() const { return passedCycles; }
bool keyboardKeys[8*7] = {0};
};

View File

@ -28,7 +28,7 @@ uint32_t Emulator::readReg8(uint32_t reg) {
} else if (reg == TC2CTRL) {
return tc2.config;
} else if (reg == PADR) {
return readKeyboard(kScan);
return readKeyboard();
} else if (reg == PBDR) {
return (portValues >> 16) & 0xFF;
} else if (reg == PCDR) {
@ -562,4 +562,99 @@ void Emulator::diffInterrupts(uint16_t oldval, uint16_t newval) {
if (changes & 0x4000) log("INTCHG lcd=%d", newval & 0x4000);
if (changes & 0x8000) log("INTCHG spi=%d", newval & 0x8000);
}
uint32_t Emulator::readKeyboard() {
if (kScan & 8) {
// Select one keyboard
return keyboardColumns[kScan & 7];
} else if (kScan == 0) {
// Report all columns combined
uint8_t val = 0;
for (int i = 0; i < 8; i++)
val |= keyboardColumns[i];
return val;
} else {
return 0;
}
}
void Emulator::setKeyboardKey(EpocKey key, bool value) {
int idx = -1;
#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
switch ((int)key) {
case EStdKeyDictaphoneRecord: KEY(0, 6);
case '1': KEY(0, 5);
case '2': KEY(0, 4);
case '3': KEY(0, 3);
case '4': KEY(0, 2);
case '5': KEY(0, 1);
case '6': KEY(0, 0);
case EStdKeyDictaphonePlay: KEY(1, 6);
case '7': KEY(1, 5);
case '8': KEY(1, 4);
case '9': KEY(1, 3);
case '0': KEY(1, 2);
case EStdKeyBackspace: KEY(1, 1);
case EStdKeySingleQuote: KEY(1, 0);
case EStdKeyEscape: KEY(2, 6);
case 'Q': KEY(2, 5);
case 'W': KEY(2, 4);
case 'E': KEY(2, 3);
case 'R': KEY(2, 2);
case 'T': KEY(2, 1);
case 'Y': KEY(2, 0);
case EStdKeyMenu: KEY(3, 6);
case 'U': KEY(3, 5);
case 'I': KEY(3, 4);
case 'O': KEY(3, 3);
case 'P': KEY(3, 2);
case 'L': KEY(3, 1);
case EStdKeyEnter: KEY(3, 0);
case EStdKeyLeftCtrl: KEY(4, 6);
case EStdKeyTab: KEY(4, 5);
case 'A': KEY(4, 4);
case 'S': KEY(4, 3);
case 'D': KEY(4, 2);
case 'F': KEY(4, 1);
case 'G': KEY(4, 0);
case EStdKeyLeftFunc: KEY(5, 6);
case 'H': KEY(5, 5);
case 'J': KEY(5, 4);
case 'K': KEY(5, 3);
case 'M': KEY(5, 2);
case EStdKeyFullStop: KEY(5, 1);
case EStdKeyDownArrow: KEY(5, 0);
case EStdKeyRightShift: KEY(6, 6);
case 'Z': KEY(6, 5);
case 'X': KEY(6, 4);
case 'C': KEY(6, 3);
case 'V': KEY(6, 2);
case 'B': KEY(6, 1);
case 'N': KEY(6, 0);
case EStdKeyLeftShift: KEY(7, 6);
case EStdKeyDictaphoneStop: KEY(7, 5);
case EStdKeySpace: KEY(7, 4);
case EStdKeyUpArrow: KEY(7, 3);
case EStdKeyComma: KEY(7, 2);
case EStdKeyLeftArrow: KEY(7, 1);
case EStdKeyRightArrow: KEY(7, 0);
}
if (idx >= 0) {
if (value)
keyboardColumns[idx >> 8] |= (idx & 0xFF);
else
keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
}
}
}

View File

@ -23,9 +23,11 @@ private:
uint32_t pwrsr = 0x00002000; // cold start flag
uint32_t lcdControl = 0;
uint32_t lcdAddress = 0;
uint32_t kScan = 0;
uint32_t rtc = 0;
uint32_t kScan = 0;
uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0};
Timer tc1, tc2;
UART uart1, uart2;
Etna etna;
@ -53,6 +55,7 @@ private:
void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval);
void diffInterrupts(uint16_t oldval, uint16_t newval);
uint32_t readKeyboard();
public:
Emulator();
@ -62,5 +65,6 @@ public:
int getLCDWidth() const override;
int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) const override;
void setKeyboardKey(EpocKey key, bool value) override;
};
}

View File

@ -110,97 +110,53 @@ void MainWindow::updateScreen()
}
static int resolveKey(int key) {
static EpocKey resolveKey(int key) {
switch (key) {
case Qt::Key_6: return 0;
case Qt::Key_5: return 1;
case Qt::Key_4: return 2;
case Qt::Key_3: return 3;
case Qt::Key_2: return 4;
case Qt::Key_1: return 5;
// missing 6: F13/rec
case Qt::Key_Apostrophe: return 7;
case Qt::Key_Backspace: return 8;
case Qt::Key_0: return 9;
case Qt::Key_9: return 10;
case Qt::Key_8: return 11;
case Qt::Key_7: return 12;
// missing 13: F15/play
case Qt::Key_Y: return 14;
case Qt::Key_T: return 15;
case Qt::Key_R: return 16;
case Qt::Key_E: return 17;
case Qt::Key_W: return 18;
case Qt::Key_Q: return 19;
case Qt::Key_Escape: return 20;
case Qt::Key_Enter: return 21;
case Qt::Key_Return: return 21;
case Qt::Key_L: return 22;
case Qt::Key_P: return 23;
case Qt::Key_O: return 24;
case Qt::Key_I: return 25;
case Qt::Key_U: return 26;
case Qt::Key_Alt: return 27; // actually Menu
case Qt::Key_G: return 28;
case Qt::Key_F: return 29;
case Qt::Key_D: return 30;
case Qt::Key_S: return 31;
case Qt::Key_A: return 32;
case Qt::Key_Tab: return 33;
case Qt::Key_Apostrophe: return EStdKeySingleQuote;
case Qt::Key_Backspace: return EStdKeyBackspace;
case Qt::Key_Escape: return EStdKeyEscape;
case Qt::Key_Enter: return EStdKeyEnter;
case Qt::Key_Return: return EStdKeyEnter;
case Qt::Key_Alt: return EStdKeyMenu;
case Qt::Key_Tab: return EStdKeyTab;
#ifdef Q_OS_MAC
case Qt::Key_Meta: return 34; // Control -> Control
case Qt::Key_Meta: return EStdKeyLeftCtrl;
#else
case Qt::Key_Control: return 34; // Control -> Control
case Qt::Key_Control: return EStdKeyLeftCtrl;
#endif
case Qt::Key_Down: return 35;
case Qt::Key_Period: return 36;
case Qt::Key_M: return 37;
case Qt::Key_K: return 38;
case Qt::Key_J: return 39;
case Qt::Key_H: return 40;
case Qt::Key_Down: return EStdKeyDownArrow;
case Qt::Key_Period: return EStdKeyFullStop;
#ifdef Q_OS_MAC
case Qt::Key_Control: return 41; // Command -> Fn
case Qt::Key_Control: return EStdKeyLeftFunc;
#else
case Qt::Key_Meta: return 41; // Super -> Fn
case Qt::Key_Meta: return EStdKeyLeftFunc;
#endif
case Qt::Key_N: return 42;
case Qt::Key_B: return 43;
case Qt::Key_V: return 44;
case Qt::Key_C: return 45;
case Qt::Key_X: return 46;
case Qt::Key_Z: return 47;
case Qt::Key_Shift: return 48;
case Qt::Key_Right: return 49;
case Qt::Key_Left: return 50;
case Qt::Key_Comma: return 51;
case Qt::Key_Up: return 52;
case Qt::Key_Space: return 53;
// missing 54: F14/stop
// missing 55: another Shift
case Qt::Key_Shift: return EStdKeyLeftShift;
case Qt::Key_Right: return EStdKeyRightArrow;
case Qt::Key_Left: return EStdKeyLeftArrow;
case Qt::Key_Comma: return EStdKeyComma;
case Qt::Key_Up: return EStdKeyUpArrow;
case Qt::Key_Space: return EStdKeySpace;
}
return -1;
if (key >= '0' && key <= '9') return (EpocKey)key;
if (key >= 'A' && key <= 'Z') return (EpocKey)key;
return EStdKeyNull;
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
int k = resolveKey(event->key());
if (k >= 0)
emu->keyboardKeys[k] = true;
EpocKey k = resolveKey(event->key());
if (k != EStdKeyNull)
emu->setKeyboardKey(k, true);
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
int k = resolveKey(event->key());
if (k >= 0)
emu->keyboardKeys[k] = false;
EpocKey k = resolveKey(event->key());
if (k != EStdKeyNull)
emu->setKeyboardKey(k, false);
}