From 83c1dcadf7b7eaadaa176be64350ff8e25f5ed06 Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Wed, 25 Dec 2019 17:02:46 +0000 Subject: [PATCH] implement touch panel for 5mx --- WindCore/etna.cpp | 6 ++++ WindCore/windermere.cpp | 63 +++++++++++++++++++++++++++++++++++--- WindCore/windermere.h | 3 ++ WindQt/pdascreenwindow.cpp | 22 +++++++++++++ 4 files changed, 90 insertions(+), 4 deletions(-) diff --git a/WindCore/etna.cpp b/WindCore/etna.cpp index d79ca82..2267db7 100644 --- a/WindCore/etna.cpp +++ b/WindCore/etna.cpp @@ -51,6 +51,12 @@ Etna::Etna(ARM710 *owner) { for (int i = 0; i < 0x80; i++) prom[i] = 0; + // defaults expected by the touchscreen code + prom[0xA] = 20; + prom[0xB] = 20; + prom[0xC] = 20; + prom[0xD] = 30; + // some basic stuff to begin with // set up the Psion's unique ID prom[0x1B] = 0xDE; diff --git a/WindCore/windermere.cpp b/WindCore/windermere.cpp index a6623be..335d3eb 100644 --- a/WindCore/windermere.cpp +++ b/WindCore/windermere.cpp @@ -72,16 +72,34 @@ uint32_t Emulator::readReg32(uint32_t reg) { return tc1.value; } else if (reg == TC2VAL) { return tc2.value; - } else if (reg == SSSR) { -// printf("!!! SSSR kludge! !!!\n"); + } else if (reg == SSDR) { + // as per 5000A7B0 in 5mx rom + uint16_t ssiValue = 0; + switch (lastSSIRequest) { +// case 0x9093: ssiValue = (uint16_t)(1156 - (touchY * 3.96)); break; +// case 0xD0D3: ssiValue = (uint16_t)(2819 - (touchX * 3.91)); break; + case 0x9093: ssiValue = (uint16_t)(1156 - (touchY * 3.96)); break; + case 0xD0D3: ssiValue = (uint16_t)(1276 + (touchX * 3.91)); break; + case 0xA4A4: ssiValue = 3100; break; // MainBattery + case 0xE4E4: ssiValue = 3100; break; // BackupBattery + } + + uint32_t ret = 0; + if (ssiReadCounter == 4) ret = (ssiValue >> 5) & 0x7F; + if (ssiReadCounter == 5) ret = (ssiValue << 3) & 0xF8; + ssiReadCounter++; + if (ssiReadCounter == 6) ssiReadCounter = 0; + + // by hardware we should be clearing SSEOTI here, i think + // but we just leave it on to simplify things + return ret; + } else if (reg == SSSR) { return 0; } else if (reg == RTCDRL) { -// uint16_t v = getRTC() & 0xFFFF; uint16_t v = rtc & 0xFFFF; // printf("RTCDRL: %04x\n", v); return v; } else if (reg == RTCDRU) { -// uint16_t v = getRTC() >> 16; uint16_t v = rtc >> 16; // printf("RTCDRU: %04x\n", v); return v; @@ -178,6 +196,9 @@ void Emulator::writeReg32(uint32_t reg, uint32_t value) { uart1.writeReg32(reg & 0xFF, value); } else if ((reg & 0xF00) == 0x700) { uart2.writeReg32(reg & 0xFF, value); + } else if (reg == SSDR) { + if (value != 0) + lastSSIRequest = (lastSSIRequest >> 8) | (value & 0xFF00); } else if (reg == TC1LOAD) { tc1.load(value); } else if (reg == TC1EOI) { @@ -475,6 +496,35 @@ void Emulator::debugPC(uint32_t pc) { log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x tableB:%08x", virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB); } + + if (pc == 0x1576C) { + uint32_t rawEvent = getGPR(0); + uint32_t evtType = readVirtualDebug(rawEvent, V32).value_or(0); + uint32_t evtTick = readVirtualDebug(rawEvent + 4, V32).value_or(0); + uint32_t evtParamA = readVirtualDebug(rawEvent + 8, V32).value_or(0); + uint32_t evtParamB = readVirtualDebug(rawEvent + 0xC, V32).value_or(0); + const char *n = "???"; + switch (evtType) { + case 0: n = "ENone"; break; + case 1: n = "EPointerMove"; break; + case 2: n = "EPointerSwitchOn"; break; + case 3: n = "EKeyDown"; break; + case 4: n = "EKeyUp"; break; + case 5: n = "ERedraw"; break; + case 6: n = "ESwitchOn"; break; + case 7: n = "EActive"; break; + case 8: n = "EInactive"; break; + case 9: n = "EUpdateModifiers"; break; + case 10: n = "EButton1Down"; break; + case 11: n = "EButton1Up"; break; + case 12: n = "EButton2Down"; break; + case 13: n = "EButton2Up"; break; + case 14: n = "EButton3Down"; break; + case 15: n = "EButton3Up"; break; + case 16: n = "ESwitchOff"; break; + } + log("EVENT %s: tick=%d params=%08x,%08x", n, evtTick, evtParamA, evtParamB); + } } @@ -660,6 +710,11 @@ void Emulator::setKeyboardKey(EpocKey key, bool value) { } void Emulator::updateTouchInput(int32_t x, int32_t y, bool down) { + pendingInterrupts &= ~(1 << EINT3); + if (down) + pendingInterrupts |= (1 << EINT3); + touchX = x; + touchY = y; } } diff --git a/WindCore/windermere.h b/WindCore/windermere.h index 36a3359..5c5d5a2 100644 --- a/WindCore/windermere.h +++ b/WindCore/windermere.h @@ -24,9 +24,12 @@ private: uint32_t lcdControl = 0; uint32_t lcdAddress = 0; uint32_t rtc = 0; + uint16_t lastSSIRequest = 0; + int ssiReadCounter = 0; uint32_t kScan = 0; uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0}; + int32_t touchX = 0, touchY = 0; Timer tc1, tc2; UART uart1, uart2; diff --git a/WindQt/pdascreenwindow.cpp b/WindQt/pdascreenwindow.cpp index 8cea790..e1db011 100644 --- a/WindQt/pdascreenwindow.cpp +++ b/WindQt/pdascreenwindow.cpp @@ -27,6 +27,28 @@ PDAScreenWindow::PDAScreenWindow(EmuBase *emu, QWidget *parent) : (new QLabel("Copy/Paste", this))->setGeometry(rightX, bitH * 2, bitW, bitH); (new QLabel("Zoom In", this))->setGeometry(rightX, bitH * 3, bitW, bitH); (new QLabel("Zoom Out", this))->setGeometry(rightX, bitH * 4, bitW, bitH); + } else if (strcmp(who, "Series 5mx") == 0) { + int leftW = emu->getLCDOffsetX(); + int leftH = emu->getLCDHeight() / 5; + (new QLabel("➡️", this))->setGeometry(0, leftH * 0, leftW, leftH); + (new QLabel("📄", this))->setGeometry(0, leftH * 1, leftW, leftH); + (new QLabel("📡", this))->setGeometry(0, leftH * 2, leftW, leftH); + (new QLabel("+", this))->setGeometry(0, leftH * 3, leftW, leftH); + (new QLabel("-", this))->setGeometry(0, leftH * 4, leftW, leftH); + + int barX = 50; + int barY = leftH * 5; + int barW = (emu->getDigitiserWidth() - barX) / 8; + int barH = emu->getDigitiserHeight() - emu->getLCDHeight(); + (new QLabel("System", this))->setGeometry(0, barY, barX, barH); + (new QLabel("Word", this))->setGeometry(barX + barW * 0, barY, barW, barH); + (new QLabel("Sheet", this))->setGeometry(barX + barW * 1, barY, barW, barH); + (new QLabel("Contacts", this))->setGeometry(barX + barW * 2, barY, barW, barH); + (new QLabel("Agenda", this))->setGeometry(barX + barW * 3, barY, barW, barH); + (new QLabel("Email", this))->setGeometry(barX + barW * 4, barY, barW, barH); + (new QLabel("Calc", this))->setGeometry(barX + barW * 5, barY, barW, barH); + (new QLabel("Jotter", this))->setGeometry(barX + barW * 6, barY, barW, barH); + (new QLabel("Extras", this))->setGeometry(barX + barW * 7, barY, barW, barH); } }