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) { uint32_t Emulator::readReg8(uint32_t reg) {
if (reg == PADR) { if (reg == PADR) {
return readKeyboard(kScan); return ((portValues >> 24) & 0x80) | (readKeyboard() & 0x7F);
} else if (reg == PBDR) { } else if (reg == PBDR) {
return (portValues >> 16) & 0xFF; return ((portValues >> 16) & 0x0F) | (keyboardExtra << 4);
} else if (reg == PDDR) { } else if (reg == PDDR) {
return (portValues >> 8) & 0xFF; return (portValues >> 8) & 0xFF;
} else if (reg == PEDR) { } 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 & 0x400000) log("PRT B6: %d", newval&0x400000);
if (changes & 0x800000) log("PRT B7: %d", newval&0x800000); 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 sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
uint32_t lcdControl = 0; uint32_t lcdControl = 0;
uint32_t lcdAddress = 0xC0000000; uint32_t lcdAddress = 0xC0000000;
uint32_t kScan = 0;
uint32_t rtc = 0; uint32_t rtc = 0;
uint32_t rtcDiv = 0; uint32_t rtcDiv = 0;
uint64_t lcdPalette = 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; Timer tc1, tc2;
CLPS7600 pcCardController; CLPS7600 pcCardController;
bool halted = false, asleep = false; bool halted = false, asleep = false;
@ -52,6 +55,7 @@ private:
void fetchProcessFilename(uint32_t obj, char *buf); void fetchProcessFilename(uint32_t obj, char *buf);
void debugPC(uint32_t pc); void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval); void diffPorts(uint32_t oldval, uint32_t newval);
uint32_t readKeyboard() const;
public: public:
Emulator(); Emulator();
@ -61,5 +65,6 @@ public:
int getLCDWidth() const override; int getLCDWidth() const override;
int getLCDHeight() const override; int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) const override; void readLCDIntoBuffer(uint8_t **lines) const override;
void setKeyboardKey(EpocKey key, bool value) override;
}; };
} }

View File

@ -1,19 +1 @@
#include "emubase.h" #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 "arm710.h"
#include <unordered_set> #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 class EmuBase : public ARM710
{ {
protected: protected:
@ -19,10 +117,9 @@ public:
virtual int getLCDWidth() const = 0; virtual int getLCDWidth() const = 0;
virtual int getLCDHeight() const = 0; virtual int getLCDHeight() const = 0;
virtual void readLCDIntoBuffer(uint8_t **lines) 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; } std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
uint64_t currentCycles() const { return passedCycles; } 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) { } else if (reg == TC2CTRL) {
return tc2.config; return tc2.config;
} else if (reg == PADR) { } else if (reg == PADR) {
return readKeyboard(kScan); return readKeyboard();
} else if (reg == PBDR) { } else if (reg == PBDR) {
return (portValues >> 16) & 0xFF; return (portValues >> 16) & 0xFF;
} else if (reg == PCDR) { } 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 & 0x4000) log("INTCHG lcd=%d", newval & 0x4000);
if (changes & 0x8000) log("INTCHG spi=%d", newval & 0x8000); 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 pwrsr = 0x00002000; // cold start flag
uint32_t lcdControl = 0; uint32_t lcdControl = 0;
uint32_t lcdAddress = 0; uint32_t lcdAddress = 0;
uint32_t kScan = 0;
uint32_t rtc = 0; uint32_t rtc = 0;
uint32_t kScan = 0;
uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0};
Timer tc1, tc2; Timer tc1, tc2;
UART uart1, uart2; UART uart1, uart2;
Etna etna; Etna etna;
@ -53,6 +55,7 @@ private:
void debugPC(uint32_t pc); void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval); void diffPorts(uint32_t oldval, uint32_t newval);
void diffInterrupts(uint16_t oldval, uint16_t newval); void diffInterrupts(uint16_t oldval, uint16_t newval);
uint32_t readKeyboard();
public: public:
Emulator(); Emulator();
@ -62,5 +65,6 @@ public:
int getLCDWidth() const override; int getLCDWidth() const override;
int getLCDHeight() const override; int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) 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) { switch (key) {
case Qt::Key_6: return 0; case Qt::Key_Apostrophe: return EStdKeySingleQuote;
case Qt::Key_5: return 1; case Qt::Key_Backspace: return EStdKeyBackspace;
case Qt::Key_4: return 2; case Qt::Key_Escape: return EStdKeyEscape;
case Qt::Key_3: return 3; case Qt::Key_Enter: return EStdKeyEnter;
case Qt::Key_2: return 4; case Qt::Key_Return: return EStdKeyEnter;
case Qt::Key_1: return 5; case Qt::Key_Alt: return EStdKeyMenu;
// missing 6: F13/rec case Qt::Key_Tab: return EStdKeyTab;
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;
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
case Qt::Key_Meta: return 34; // Control -> Control case Qt::Key_Meta: return EStdKeyLeftCtrl;
#else #else
case Qt::Key_Control: return 34; // Control -> Control case Qt::Key_Control: return EStdKeyLeftCtrl;
#endif #endif
case Qt::Key_Down: return EStdKeyDownArrow;
case Qt::Key_Down: return 35; case Qt::Key_Period: return EStdKeyFullStop;
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;
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
case Qt::Key_Control: return 41; // Command -> Fn case Qt::Key_Control: return EStdKeyLeftFunc;
#else #else
case Qt::Key_Meta: return 41; // Super -> Fn case Qt::Key_Meta: return EStdKeyLeftFunc;
#endif #endif
case Qt::Key_Shift: return EStdKeyLeftShift;
case Qt::Key_N: return 42; case Qt::Key_Right: return EStdKeyRightArrow;
case Qt::Key_B: return 43; case Qt::Key_Left: return EStdKeyLeftArrow;
case Qt::Key_V: return 44; case Qt::Key_Comma: return EStdKeyComma;
case Qt::Key_C: return 45; case Qt::Key_Up: return EStdKeyUpArrow;
case Qt::Key_X: return 46; case Qt::Key_Space: return EStdKeySpace;
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
} }
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) void MainWindow::keyPressEvent(QKeyEvent *event)
{ {
int k = resolveKey(event->key()); EpocKey k = resolveKey(event->key());
if (k >= 0) if (k != EStdKeyNull)
emu->keyboardKeys[k] = true; emu->setKeyboardKey(k, true);
} }
void MainWindow::keyReleaseEvent(QKeyEvent *event) void MainWindow::keyReleaseEvent(QKeyEvent *event)
{ {
int k = resolveKey(event->key()); EpocKey k = resolveKey(event->key());
if (k >= 0) if (k != EStdKeyNull)
emu->keyboardKeys[k] = false; emu->setKeyboardKey(k, false);
} }