From d39c73415125a4d4963bef29cd52a81a5364b661 Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Sat, 31 Aug 2019 13:26:23 +0200 Subject: [PATCH 1/8] Experimental Pi Zero 1541 loading support. Experimental Pi Zero 1541 loading support. Disables screens, keyboard, uart, interrupts. Restructured 1541 emulation loop to avoid button polling. Drive reading code optimized. --- Makefile.rules | 2 +- src/DiskCaddy.cpp | 14 ++- src/DiskCaddy.h | 18 +++- src/Drive.cpp | 142 +++++++++++++++++++++++++++- src/Drive.h | 36 ++++++- src/FileBrowser.cpp | 56 +++++++++-- src/FileBrowser.h | 15 ++- src/InputMappings.cpp | 9 +- src/InputMappings.h | 22 ++++- src/Keyboard.cpp | 3 +- src/Keyboard.h | 2 + src/Screen.cpp | 8 ++ src/armc-cstubs.c | 2 + src/iec_bus.cpp | 4 +- src/iec_bus.h | 8 ++ src/interrupt.c | 15 ++- src/main.cpp | 214 ++++++++++++++++++++++++++++++++++++++---- src/options.h | 4 + 18 files changed, 525 insertions(+), 49 deletions(-) diff --git a/Makefile.rules b/Makefile.rules index d4679f5..1fe4669 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -13,7 +13,7 @@ LD = $(PREFIX)ld AR = $(PREFIX)ar ifeq ($(strip $(RASPPI)),0) -ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIZERO=1 +ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIZERO=1 -DEXPERIMENTALZERO=1 CFLAGS += -DRPIZERO=1 -DRASPPI=1 else ifeq ($(strip $(RASPPI)),1) ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIBPLUS=1 diff --git a/src/DiskCaddy.cpp b/src/DiskCaddy.cpp index cd8bbcc..1954106 100644 --- a/src/DiskCaddy.cpp +++ b/src/DiskCaddy.cpp @@ -44,6 +44,7 @@ bool DiskCaddy::Empty() if (disks[index].IsDirty()) { anyDirty = true; +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections); @@ -67,12 +68,14 @@ bool DiskCaddy::Empty() screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } +#endif } disks[index].Close(); } if (anyDirty) { +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections); @@ -96,6 +99,7 @@ bool DiskCaddy::Empty() screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } +#endif } disks.clear(); @@ -112,6 +116,7 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly) FRESULT res = f_open(&fp, fileInfo->fname, FA_READ); if (res == FR_OK) { +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections); @@ -135,7 +140,7 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly) screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } - +#endif u32 bytesRead; SetACTLed(true); f_read(&fp, DiskImage::readBuffer, READBUFFER_SIZE, &bytesRead); @@ -254,6 +259,7 @@ void DiskCaddy::Display() unsigned caddyIndex; int x; int y; +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections); @@ -281,6 +287,7 @@ void DiskCaddy::Display() // RGBA BkColour = RGBA(0, 0, 0, 0xFF); // screenLCD->Clear(BkColour); //} +#endif ShowSelectedImage(0); } @@ -288,6 +295,7 @@ void DiskCaddy::ShowSelectedImage(u32 index) { u32 x; u32 y; +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections) - 16; @@ -343,6 +351,7 @@ void DiskCaddy::ShowSelectedImage(u32 index) } screenLCD->SwapBuffers(); } +#endif } bool DiskCaddy::Update() @@ -352,6 +361,7 @@ bool DiskCaddy::Update() u32 caddyIndex = GetSelectedIndex(); if (caddyIndex != oldCaddyIndex) { +#if not defined(EXPERIMENTALZERO) if (screen) { x = screen->ScaleX(screenPosXCaddySelections) - 16; @@ -366,7 +376,7 @@ bool DiskCaddy::Update() { } - +#endif return true; } return false; diff --git a/src/DiskCaddy.h b/src/DiskCaddy.h index e8d881f..fb86de4 100644 --- a/src/DiskCaddy.h +++ b/src/DiskCaddy.h @@ -28,12 +28,17 @@ class DiskCaddy public: DiskCaddy() : selectedIndex(0) +#if not defined(EXPERIMENTALZERO) , screen(0) , screenLCD(0) +#endif { } - +#if defined(EXPERIMENTALZERO) + void SetScreen() { } +#else void SetScreen(Screen* screen, ScreenBase* screenLCD) { this->screen = screen; this->screenLCD = screenLCD; } +#endif bool Empty(); @@ -55,9 +60,11 @@ public: DiskImage* PrevDisk() { - --selectedIndex; - if ((int)selectedIndex < 0) - selectedIndex += (u32)disks.size(); + if (selectedIndex == 0u) + selectedIndex += (u32)disks.size()-1; + else + --selectedIndex; + return GetCurrentDisk(); } @@ -99,9 +106,10 @@ private: std::vector disks; u32 selectedIndex; u32 oldCaddyIndex; - +#if not defined(EXPERIMENTALZERO) ScreenBase* screen; ScreenBase* screenLCD; +#endif }; #endif \ No newline at end of file diff --git a/src/Drive.cpp b/src/Drive.cpp index f05b519..a7b2a28 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -346,12 +346,19 @@ extern "C" Drive::Drive() : m_pVIA(0) { - Reset(); srand(0x811c9dc5U); +#if defined(EXPERIMENTALZERO) + localSeed = 0x811c9dc5U; +#endif + Reset(); } void Drive::Reset() { +#if defined(EXPERIMENTALZERO) + LED = false; + cyclesForBit = 0; +#endif headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz) UpdateHeadSectorPosition(); @@ -361,7 +368,12 @@ void Drive::Reset() readShiftRegister = 0; writeShiftRegister = 0; UE3Counter = 0; +#if defined(EXPERIMENTALZERO) + ResetEncoderDecoder(18 * 16, 4 * 16); + cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); +#else ResetEncoderDecoder(18.0f, 22.0f); +#endif newDiskImageQueuedCylesRemaining = DISK_SWAP_CYCLES_DISK_EJECTING + DISK_SWAP_CYCLES_NO_DISK + DISK_SWAP_CYCLES_DISK_INSERTING; m_pVIA->InputCA1(true); // Reset in read mode m_pVIA->InputCB1(true); @@ -456,6 +468,12 @@ bool Drive::Update() // UE6 provides the CPU's clock by dividing the 16Mhz clock by 16. // UE7 (a 74ls193 4bit counter) counts up on the falling edge of the 16Mhz clock. UE7 drives the Encoder/Decoder clock. // So we need to simulate 16 cycles for every 1 CPU cycle +#if defined(EXPERIMENTALZERO) + if (writing) + DriveLoopWrite(); + else + DriveLoopRead(); +#else for (int cycles = 0; cycles < 16; ++cycles) { if (!writing) @@ -534,6 +552,7 @@ bool Drive::Update() } } } +#endif } m_pVIA->InputCA1(!SO); @@ -544,3 +563,124 @@ bool Drive::Update() return dataReady; } + +#if defined(EXPERIMENTALZERO) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +void Drive::DriveLoopRead() +{ + unsigned int minCycles; + unsigned int cycles = 0; + + while (true) + { + minCycles = min(min(cyclesLeftForBit, fluxReversalCyclesLeft), 16 - max(UE7Counter, cycles)); + cyclesLeftForBit -= minCycles; + fluxReversalCyclesLeft -= minCycles; + cycles += minCycles; + UE7Counter += minCycles; + + if (cycles == 16) + return; + + if (cyclesLeftForBit == 0) + { + //which is faster? single loop ceil check or the 3 lines below? + float fn = 2.0f * cyclesPerBit - cyclesForBit; + cyclesLeftForBit = (int)fn; + cyclesForBit = cyclesPerBit; + if (fn != (float)cyclesLeftForBit) { + ++cyclesLeftForBit; + ++cyclesForBit; + } + + //cyclesForBit -= cyclesPerBit; + //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); + //cyclesForBit += cyclesLeftForBit; + + if (GetNextBit()) + { + ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); + } + } + + if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen + { + ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one. + } + + if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. + { + UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. + ++UF4Counter &= 0xf; // Clock and clamp UF4. + // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) + // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) + if ((UF4Counter & 0x3) == 2) + { + readShiftRegister <<= 1; + readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + + writeShiftRegister <<= 1; + // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. + if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC + { + UE3Counter = 0; // Phase lock on to byte boundary + m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC + } + else + { + m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits + UE3Counter++; + } + } + // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 + else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary + { + UE3Counter = 0; + SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. + writeShiftRegister = (u8)(readShiftRegister & 0xff); + m_pVIA->GetPortA()->SetInput(writeShiftRegister); + } + } + + + }; +} + +void Drive::DriveLoopWrite() +{ + unsigned int minCycles; + unsigned int cycles = 0; + for (unsigned int cycles = 0; cycles != 16; ++cycles) + { + if (++UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. + { + UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. + ++UF4Counter &= 0xf; // Clock and clamp UF4. + // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) + // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) + if ((UF4Counter & 0x3) == 2) + { + readShiftRegister <<= 1; + readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + + SetNextBit((writeShiftRegister & 0x80)); + + writeShiftRegister <<= 1; + // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. + UE3Counter++; + } + // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 + else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary + { + UE3Counter = 0; + SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. + writeShiftRegister = m_pVIA->GetPortA()->GetOutput(); + } + } + } +} +#endif \ No newline at end of file diff --git a/src/Drive.h b/src/Drive.h index 1640358..3d15553 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -23,6 +23,17 @@ #include "DiskImage.h" #include +#if defined(EXPERIMENTALZERO) +inline int ceil(float num) { + int inum = (int)num; + if (num == (float)inum) { + return inum; + } + return inum + 1; +} +#endif + + class Drive { public: @@ -37,6 +48,11 @@ public: static void OnPortOut(void*, unsigned char status); bool Update(); +#if defined(EXPERIMENTALZERO) + void DriveLoopWrite(); + void DriveLoopRead(); +#endif + void Insert(DiskImage* diskImage); inline const DiskImage* GetDiskImage() const { return diskImage; } void Eject(); @@ -49,6 +65,16 @@ public: inline unsigned char GetLastHeadDirection() const { return lastHeadDirection; } // For simulated head movement sounds private: +#if defined(EXPERIMENTALZERO) + int32_t localSeed; + inline void ResetEncoderDecoder(unsigned int min, unsigned int /*max*/span) + { + UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) + UF4Counter = 0; + localSeed = ((localSeed * 1103515245) + 12345) & 0x7fffffff; + fluxReversalCyclesLeft = (span) * (localSeed >> 11) + min; + } +#else inline float GenerateRandomFluxReversalTime(float min, float max) { return ((max - min) * ((float)rand() / RAND_MAX)) + min; } // Inputs in micro seconds inline void ResetEncoderDecoder(float min, float max) @@ -57,6 +83,7 @@ private: UF4Counter = 0; randomFluxReversalTime = GenerateRandomFluxReversalTime(min, max); } +#endif inline void UpdateHeadSectorPosition() { // Disk spins at 300rpm = 5rps so to calculate how many 16Mhz cycles one rotation takes;- @@ -132,13 +159,18 @@ private: // CB2 (output) // - R/!W m6522* m_pVIA; - +#if defined(EXPERIMENTALZERO) + unsigned int cyclesLeftForBit; + unsigned int fluxReversalCyclesLeft; + unsigned int UE7Counter; +#else + int UE7Counter; +#endif float cyclesForBit; u32 readShiftRegister; unsigned headTrackPos; u32 headBitOffset; float randomFluxReversalTime; - int UE7Counter; int UF4Counter; int UE3Counter; int CLOCK_SEL_AB; diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index 1f8bd95..9eb6969 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -82,6 +82,7 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b if (entryIndex < list->entries.size()) { FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex]; +#if not defined(EXPERIMENTALZERO) if (screen->IsLCD()) { // pre-clear line on OLED @@ -111,9 +112,10 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b { snprintf(buffer2, 256, "%s", entry->filImage.fname); } +#endif int len = strlen(buffer2 + highlightScrollOffset); strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1)); - +#if not defined(EXPERIMENTALZERO) if (!screen->IsLCD()) { // space pad the remainder of the line (but not on OLED) @@ -121,46 +123,56 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b buffer1[len++] = ' '; buffer1[columnsMax] = 0; } - +#endif if (selected) { if (entry->filImage.fattrib & AM_DIR) { +#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], RGBA(0xff, 0xff, 0xff, 0xff)); +#endif } else { colour = RGBA(0xff, 0, 0, 0xff); if (entry->filImage.fattrib & AM_RDO) colour = palette[VIC2_COLOUR_INDEX_RED]; - +#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff)); +#endif } } else { if (entry->filImage.fattrib & AM_DIR) { +#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], BkColour); +#endif } else { colour = palette[VIC2_COLOUR_INDEX_LGREY]; if (entry->filImage.fattrib & AM_RDO) colour = palette[VIC2_COLOUR_INDEX_PINK]; +#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, colour, BkColour); +#endif } } } else // line is blank, write spaces { memset(buffer1, ' ', columnsMax); +#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, BkColour, BkColour); +#endif } } void FileBrowser::BrowsableListView::Refresh() { +#if not defined(EXPERIMENTALZERO) u32 index; u32 entryIndex; u32 x = positionX; @@ -185,6 +197,7 @@ void FileBrowser::BrowsableListView::Refresh() } screen->SwapBuffers(); +#endif } void FileBrowser::BrowsableListView::RefreshHighlightScroll() @@ -192,6 +205,7 @@ void FileBrowser::BrowsableListView::RefreshHighlightScroll() char buffer2[256] = { 0 }; FileBrowser::BrowsableList::Entry* entry = list->current; +#if not defined(EXPERIMENTALZERO) if (screen->IsMonocrome()) { if (entry->filImage.fattrib & AM_DIR) @@ -254,6 +268,7 @@ void FileBrowser::BrowsableListView::RefreshHighlightScroll() screen->RefreshRows(rowIndex, 1); } +#endif } bool FileBrowser::BrowsableListView::CheckBrowseNavigation(bool pageOnly) @@ -499,11 +514,14 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM , roms(roms) , deviceID(deviceID) , displayPNGIcons(displayPNGIcons) +#if not defined(EXPERIMENTALZERO) , screenMain(screenMain) , screenLCD(screenLCD) +#endif , scrollHighlightRate(scrollHighlightRate) , displayingDevices(false) { +#if not defined(EXPERIMENTALZERO) u32 columns = screenMain->ScaleX(80); u32 rows = (int)(38.0f * screenMain->GetScaleY()); u32 positionX = 0; @@ -530,6 +548,7 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM folder.AddView(screenLCD, inputMappings, columns, rows, positionX, positionY, true); } +#endif } u32 FileBrowser::Colour(int index) @@ -690,7 +709,7 @@ void FileBrowser::DeviceSwitched() m_IEC_Commands.SetDisplayingDevices(displayingDevices); FolderChanged(); } - +#if not defined(EXPERIMENTALZERO) /* void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected) { @@ -769,9 +788,10 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow } } */ - +#endif void FileBrowser::RefeshDisplay() { +#if not defined(EXPERIMENTALZERO) u32 textColour = Colour(VIC2_COLOUR_INDEX_LGREEN); u32 bgColour = Colour(VIC2_COLOUR_INDEX_GREY); char buffer[1024]; @@ -780,11 +800,11 @@ void FileBrowser::RefeshDisplay() screenMain->DrawRectangle(0, 0, (int)screenMain->Width(), 17, bgColour); screenMain->PrintText(false, 0, 0, buffer, textColour, bgColour); } - +#if not defined(EXPERIMENTALZERO) //u32 offsetX = screenMain->ScaleX(1024 - 320); //RefeshDisplayForBrowsableList(&folder, 0); //RefeshDisplayForBrowsableList(&caddySelections, offsetX, false); - +#endif folder.RefreshViews(); caddySelections.RefreshViews(); @@ -796,10 +816,14 @@ void FileBrowser::RefeshDisplay() u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y); screenMain->PrintText(false, 0, y, folder.searchPrefix, textColour, bgColour); } +#endif } bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon) { +#if defined(EXPERIMENTALZERO) + return false; +#else bool foundValid = false; filIcon.fname[0] = 0; @@ -821,6 +845,7 @@ bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon) } } return foundValid; +#endif } void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y) @@ -843,6 +868,8 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y) int h; int channels_in_file; stbi_uc* image = stbi_load_from_memory((stbi_uc const*)PNG, bytesRead, &w, &h, &channels_in_file, 4); +#if not defined(EXPERIMENTALZERO) + if (image && (w == PNG_WIDTH && h == PNG_HEIGHT)) { //DEBUG_LOG("Opened PNG %s w = %d h = %d cif = %d\r\n", fileName, w, h, channels_in_file); @@ -852,6 +879,7 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y) { //DEBUG_LOG("Invalid PNG size %d x %d\r\n", w, h); } +#endif } } else @@ -862,6 +890,7 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y) void FileBrowser::DisplayPNG() { +#if not defined(EXPERIMENTALZERO) if (displayPNGIcons && folder.current) { FileBrowser::BrowsableList::Entry* current = folder.current; @@ -869,6 +898,7 @@ void FileBrowser::DisplayPNG() u32 y = screenMain->ScaleY(666) - PNG_HEIGHT; DisplayPNG(current->filIcon, x, y); } +#endif } int FileBrowser::IsAtRootOfDevice() @@ -1369,18 +1399,22 @@ void FileBrowser::UpdateInputDiskCaddy() void FileBrowser::DisplayStatusBar() { +#if not defined(EXPERIMENTALZERO) u32 x = 0; u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y); char bufferOut[128]; snprintf(bufferOut, 128, "LED 0 Motor 0 Track 18.0 ATN 0 DAT 0 CLK 0"); screenMain->PrintText(false, x, y, bufferOut, RGBA(0, 0, 0, 0xff), RGBA(0xff, 0xff, 0xff, 0xff)); +#endif } void FileBrowser::ClearScreen() { +#if not defined(EXPERIMENTALZERO) u32 bgColour = palette[VIC2_COLOUR_INDEX_BLUE]; screenMain->Clear(bgColour); +#endif } void FileBrowser::ClearSelections() @@ -1397,6 +1431,7 @@ void FileBrowser::ShowDeviceAndROM() u32 textColour = RGBA(0, 0, 0, 0xff); u32 bgColour = RGBA(0xff, 0xff, 0xff, 0xff); u32 x = 0; // 43 * 8 +#if not defined(EXPERIMENTALZERO) u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y) - 20; snprintf(buffer, 256, "Device %2d %*s\r\n" @@ -1405,10 +1440,12 @@ void FileBrowser::ShowDeviceAndROM() , roms->ROMNames[roms->currentROMIndex] ); screenMain->PrintText(false, x, y, buffer, textColour, bgColour); +#endif } void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForIcon) { +#if not defined(EXPERIMENTALZERO) // Ideally we should not have to load the entire disk to read the directory. static const char* fileTypes[]= { @@ -1420,7 +1457,11 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI char name[17] = { 0 }; unsigned char buffer[260] = { 0 }; int charIndex; +#if defined(EXPERIMENTALZERO) + u32 fontHeight = 16; +#else u32 fontHeight = screenMain->GetFontHeightDirectoryDisplay(); +#endif u32 x = 0; u32 y = 0; char bufferOut[128] = { 0 }; @@ -1626,6 +1667,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI DisplayPNG(filIcon, x, y); } } +#endif } void FileBrowser::SelectAutoMountImage(const char* image) diff --git a/src/FileBrowser.h b/src/FileBrowser.h index c5875fc..bfc9c7f 100644 --- a/src/FileBrowser.h +++ b/src/FileBrowser.h @@ -63,7 +63,9 @@ public: BrowsableListView(BrowsableList* list, InputMappings* inputMappings, ScreenBase* screen, u32 columns, u32 rows, u32 positionX, u32 positionY, bool lcdPgUpDown) : list(list) , inputMappings(inputMappings) +#if not defined(EXPERIMENTALZERO) , screen(screen) +#endif , columns(columns) , rows(rows) , positionX(positionX) @@ -84,8 +86,9 @@ public: BrowsableList* list; u32 offset; InputMappings* inputMappings; - +#if not defined(EXPERIMENTALZERO) ScreenBase* screen; +#endif u32 columns; u32 rows; u32 positionX; @@ -212,12 +215,14 @@ private: void RefreshFolderEntries(); void UpdateInputFolders(); +#if not defined(EXPERIMENTALZERO) //void UpdateInputDiskCaddy(); +#endif void UpdateCurrentHighlight(); - +#if not defined(EXPERIMENTALZERO) //void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true); - +#endif bool FillCaddyWithSelections(); bool AddToCaddy(FileBrowser::BrowsableList::Entry* current); @@ -249,10 +254,10 @@ private: bool buttonChangedROMDevice; BrowsableList caddySelections; - +#if not defined(EXPERIMENTALZERO) ScreenBase* screenMain; ScreenBase* screenLCD; - +#endif float scrollHighlightRate; bool displayingDevices; diff --git a/src/InputMappings.cpp b/src/InputMappings.cpp index 541045c..1a138a0 100644 --- a/src/InputMappings.cpp +++ b/src/InputMappings.cpp @@ -1,3 +1,4 @@ + // Pi1541 - A Commodore 1541 disk drive emulator // Copyright(C) 2018 Stephen White // @@ -217,9 +218,11 @@ void InputMappings::CheckButtonsEmulationMode() bool InputMappings::CheckKeyboardBrowseMode() { +#if not defined(EXPERIMENTALZERO) Keyboard* keyboard = Keyboard::Instance(); - +#endif keyboardFlags = 0; +#if not defined(EXPERIMENTALZERO) keyboardNumLetter = 0; if (!keyboard->CheckChanged()) { @@ -305,12 +308,13 @@ bool InputMappings::CheckKeyboardBrowseMode() } } } - +#endif return keyboardFlags != 0; } void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned numberOfImagesMax) { +#if not defined(EXPERIMENTALZERO) Keyboard* keyboard = Keyboard::Instance(); keyboardFlags = 0; @@ -341,5 +345,6 @@ void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned directDiskSwapRequest |= (1 << index); } } +#endif } diff --git a/src/InputMappings.h b/src/InputMappings.h index e0dad43..d00714f 100644 --- a/src/InputMappings.h +++ b/src/InputMappings.h @@ -103,21 +103,37 @@ public: keyboardBrowseLCDScreen = value; } +#if defined(EXPERIMENTALZERO) inline bool Exit() { - return KeyboardFlag(ESC_FLAG)/* | UartFlag(ESC_FLAG)*/ | ButtonFlag(ESC_FLAG); + return /*KeyboardFlag(ESC_FLAG) | UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG); } inline bool NextDisk() { - return KeyboardFlag(NEXT_FLAG)/* | UartFlag(NEXT_FLAG)*/ | ButtonFlag(NEXT_FLAG); + return /*KeyboardFlag(NEXT_FLAG) | UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG); } inline bool PrevDisk() { - return KeyboardFlag(PREV_FLAG)/* | UartFlag(PREV_FLAG)*/ | ButtonFlag(PREV_FLAG); + return /*KeyboardFlag(PREV_FLAG) | UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG); + } +#else + inline bool Exit() + { + return KeyboardFlag(ESC_FLAG) /*| UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG); } + inline bool NextDisk() + { + return KeyboardFlag(NEXT_FLAG) /*| UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG); + } + + inline bool PrevDisk() + { + return KeyboardFlag(PREV_FLAG) /*| UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG); + } +#endif inline bool AutoLoad() { return KeyboardFlag(AUTOLOAD_FLAG); } inline bool FakeReset() { return KeyboardFlag(FAKERESET_FLAG); } diff --git a/src/Keyboard.cpp b/src/Keyboard.cpp index c3f843c..01c2b7d 100644 --- a/src/Keyboard.cpp +++ b/src/Keyboard.cpp @@ -15,7 +15,7 @@ // // You should have received a copy of the GNU General Public License // along with Pi1541. If not, see . - +#if not defined(EXPERIMENTALZERO) #include "Keyboard.h" #include #include @@ -156,3 +156,4 @@ Keyboard::Keyboard() memset(keyRepeatCount, 0, sizeof(keyRepeatCount)); USPiKeyboardRegisterKeyStatusHandlerRaw(KeyPressedHandlerRaw); } +#endif diff --git a/src/Keyboard.h b/src/Keyboard.h index cfbd1e6..b0e9b0c 100644 --- a/src/Keyboard.h +++ b/src/Keyboard.h @@ -24,6 +24,7 @@ extern "C" { #include } +#if not defined(EXPERIMENTALZERO) #define MAX_KEYS 0x7f @@ -356,3 +357,4 @@ public: static Keyboard* instance; }; #endif +#endif \ No newline at end of file diff --git a/src/Screen.cpp b/src/Screen.cpp index 999718d..6118b5d 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -129,21 +129,29 @@ void Screen::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth) void Screen::PlotPixel32(u32 pixel_offset, RGBA Colour) { +#if not defined(EXPERIMENTALZERO) *((volatile RGBA*)&framebuffer[pixel_offset]) = Colour; +#endif } void Screen::PlotPixel24(u32 pixel_offset, RGBA Colour) { +#if not defined(EXPERIMENTALZERO) framebuffer[pixel_offset++] = BLUE(Colour); framebuffer[pixel_offset++] = GREEN(Colour); framebuffer[pixel_offset++] = RED(Colour); +#endif } void Screen::PlotPixel16(u32 pixel_offset, RGBA Colour) { +#if not defined(EXPERIMENTALZERO) *(unsigned short*)&framebuffer[pixel_offset] = ((RED(Colour) >> 3) << 11) | ((GREEN(Colour) >> 2) << 5) | (BLUE(Colour) >> 3); +#endif } void Screen::PlotPixel8(u32 pixel_offset, RGBA Colour) { +#if not defined(EXPERIMENTALZERO) framebuffer[pixel_offset++] = RED(Colour); +#endif } void Screen::DrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour) diff --git a/src/armc-cstubs.c b/src/armc-cstubs.c index 8fb4e29..7b16f20 100644 --- a/src/armc-cstubs.c +++ b/src/armc-cstubs.c @@ -236,7 +236,9 @@ int wait(int *status) void outbyte(char b) { +#ifndef EXPERIMENTALZERO RPI_AuxMiniUartWrite(b); +#endif } /* Write to a file. libc subroutines will use this system routine for output to diff --git a/src/iec_bus.cpp b/src/iec_bus.cpp index e77c468..a6bd0ef 100644 --- a/src/iec_bus.cpp +++ b/src/iec_bus.cpp @@ -335,10 +335,10 @@ void IEC_Bus::RefreshOuts1541(void) if (OutputLED) set |= 1 << PIGPIO_OUT_LED; else clear |= 1 << PIGPIO_OUT_LED; - +#if not defined(EXPERIMENTALZERO) if (OutputSound) set |= 1 << PIGPIO_OUT_SOUND; else clear |= 1 << PIGPIO_OUT_SOUND; - +#endif if (oldClears != clear) { write32(ARM_GPIO_GPCLR0, clear); diff --git a/src/iec_bus.h b/src/iec_bus.h index 76f2a98..553b5e0 100644 --- a/src/iec_bus.h +++ b/src/iec_bus.h @@ -135,6 +135,7 @@ enum PIGPIOMasks PIGPIO_MASK_IN_BUTTON3 = 1 << PIGPIO_IN_BUTTON3, PIGPIO_MASK_IN_BUTTON4 = 1 << PIGPIO_IN_BUTTON4, PIGPIO_MASK_IN_BUTTON5 = 1 << PIGPIO_IN_BUTTON5, + PIGPIO_MASK_ANY_BUTTON = PIGPIO_MASK_IN_BUTTON1 | PIGPIO_MASK_IN_BUTTON2 | PIGPIO_MASK_IN_BUTTON3 | PIGPIO_MASK_IN_BUTTON4 | PIGPIO_MASK_IN_BUTTON5 }; static const unsigned ButtonPinFlags[5] = { PIGPIO_MASK_IN_BUTTON1, PIGPIO_MASK_IN_BUTTON2, PIGPIO_MASK_IN_BUTTON3, PIGPIO_MASK_IN_BUTTON4, PIGPIO_MASK_IN_BUTTON5 }; @@ -316,6 +317,13 @@ public: RefreshOuts1581(); } +#if defined(EXPERIMENTALZERO) + static inline bool AnyButtonPressed() + { + return ((gplev0 & PIGPIO_MASK_ANY_BUTTON) != PIGPIO_MASK_ANY_BUTTON); + } +#endif + static inline void UpdateButton(int index, unsigned gplev0) { bool inputcurrent = (gplev0 & ButtonPinFlags[index]) == 0; diff --git a/src/interrupt.c b/src/interrupt.c index 31694e7..dc8c793 100644 --- a/src/interrupt.c +++ b/src/interrupt.c @@ -39,16 +39,19 @@ void InterruptSystemInitialize() write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2)); DataMemBarrier(); - +#ifndef EXPERIMENTALZERO EnableInterrupts(); +#endif } void InterruptSystemConnectIRQ(unsigned IRQIndex, IRQHandler* handler, void* param) { +#ifndef EXPERIMENTALZERO IRQHandlers[IRQIndex] = handler; Params[IRQIndex] = param; InterruptSystemEnableIRQ(IRQIndex); +#endif } void InterruptSystemDisconnectIRQ(unsigned IRQIndex) @@ -61,10 +64,12 @@ void InterruptSystemDisconnectIRQ(unsigned IRQIndex) void InterruptSystemEnableIRQ(unsigned IRQIndex) { - //DEBUG_LOG("InterruptSystemEnableIRQ %d\r\n", IRQIndex); +#ifndef EXPERIMENTALZERO + DEBUG_LOG("InterruptSystemEnableIRQ %d\r\n", IRQIndex); DataMemBarrier(); write32(ARM_IC_IRQS_ENABLE(IRQIndex), ARM_IRQ_MASK(IRQIndex)); DataMemBarrier(); +#endif } void InterruptSystemDisableIRQ(unsigned IRQIndex) @@ -110,11 +115,13 @@ void InterruptHandler(void) if (pendValue & IRQIndexMask) { +#ifndef EXPERIMENTALZERO IRQHandler* pHandler = IRQHandlers[IRQIndex]; if (pHandler != 0) (*pHandler)(Params[IRQIndex]); else +#endif InterruptSystemDisableIRQ(IRQIndex); } } @@ -127,11 +134,13 @@ void InterruptHandler(void) if (pendValue & IRQIndexMask) { +#ifndef EXPERIMENTALZERO IRQHandler* pHandler = IRQHandlers[IRQIndex]; if (pHandler != 0) (*pHandler)(Params[IRQIndex]); else +#endif InterruptSystemDisableIRQ(IRQIndex); } } @@ -144,11 +153,13 @@ void InterruptHandler(void) if (pendValue & IRQIndexMask) { +#ifndef EXPERIMENTALZERO IRQHandler* pHandler = IRQHandlers[IRQIndex]; if (pHandler != 0) (*pHandler)(Params[IRQIndex]); else +#endif InterruptSystemDisableIRQ(IRQIndex); } } diff --git a/src/main.cpp b/src/main.cpp index c5bcd9b..f32312a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,9 @@ const char* fileBrowserSelectedName; u8 deviceID = 8; IEC_Commands m_IEC_Commands; InputMappings* inputMappings; +#if not defined(EXPERIMENTALZERO) Keyboard* keyboard; +#endif bool USBKeyboardDetected = false; //bool resetWhileEmulating = false; bool selectedViaIECCommands = false; @@ -225,8 +227,9 @@ void InitialiseHardware() RPI_TouchInit(); #endif +#if not defined(EXPERIMENTALZERO) screen.Open(screenWidth, screenHeight, 16); - +#endif RPI_PropertyInit(); RPI_PropertyAddTag(TAG_GET_MAX_CLOCK_RATE, ARM_CLK_ID); RPI_PropertyProcess(); @@ -244,7 +247,7 @@ void InitialiseHardware() void InitialiseLCD() { - +#if not defined(EXPERIMENTALZERO) FILINFO filLcdIcon; int i2cBusMaster = options.I2CBusMaster(); @@ -306,6 +309,7 @@ void InitialiseLCD() screenLCD->RefreshScreen(); } else +#endif { screenLCD = 0; } @@ -326,6 +330,7 @@ void InitialiseLCD() // Care must be taken not to crowd out the shared cache with core1 as this could slow down core1 so that it no longer can perform its duties in the 1us timings it requires. void UpdateScreen() { +#if not defined(EXPERIMENTALZERO) bool oldLED = false; bool oldMotor = false; bool oldATN = false; @@ -555,6 +560,7 @@ void UpdateScreen() // Go back to sleep. The USB irq will wake us up again. __asm ("WFE"); } +#endif } static bool Snoop(u8 a) @@ -621,7 +627,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc inputMappings->WaitForClearButtons(); return IEC_COMMANDS; } - +#if not defined(EXPERIMENTALZERO) static u32* dmaSound; struct DMA_ControlBlock @@ -646,13 +652,15 @@ DMA_ControlBlock dmaSoundCB = 0,//&dmaSoundCB, 0, 0 }; - +#endif static void PlaySoundDMA() { +#if not defined(EXPERIMENTALZERO) write32(PWM_DMAC, PWM_ENAB + 0x0001); write32(DMA_ENABLE, 1); // DMA_EN0 write32(DMA0_BASE + DMA_CONBLK_AD, (u32)&dmaSoundCB); write32(DMA0_BASE + DMA_CS, DMA_ACTIVE); +#endif } void GlobalSetDeviceID(u8 id) @@ -684,6 +692,157 @@ void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser) } } +EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) +{ + bool oldLED = false; + unsigned ctBefore = 0; + unsigned ctAfter = 0; + int cycleCount = 0; + unsigned caddyIndex; + int headSoundCounter = 0; + int headSoundFreqCounter = 0; + // const int headSoundFreq = 833; // 1200Hz = 1/1200 * 10^6; + const int headSoundFreq = 1000000 / options.SoundOnGPIOFreq(); // 1200Hz = 1/1200 * 10^6; + unsigned char oldHeadDir; + int resetCount = 0; + bool refreshOutsAfterCPUStep = true; + unsigned numberOfImages = diskCaddy.GetNumberOfImages(); + unsigned numberOfImagesMax = numberOfImages; + if (numberOfImagesMax > 10) + numberOfImagesMax = 10; + + core0RefreshingScreen.Acquire(); + diskCaddy.Display(); + core0RefreshingScreen.Release(); + + inputMappings->directDiskSwapRequest = 0; + // Force an update on all the buttons now before we start emulation mode. + IEC_Bus::ReadBrowseMode(); + + bool extraRAM = options.GetExtraRAM(); + DataBusReadFn dataBusRead = extraRAM ? read6502ExtraRAM : read6502; + DataBusWriteFn dataBusWrite = extraRAM ? write6502ExtraRAM : write6502; + M6502& m6502 = pi1541.m6502; + m6502.SetBusFunctions(dataBusRead, dataBusWrite); + + IEC_Bus::VIA = &pi1541.VIA[0]; + IEC_Bus::port = pi1541.VIA[0].GetPortB(); + pi1541.Reset(); // will call IEC_Bus::Reset(); + IEC_Bus::OutputLED = false; + IEC_Bus::LetSRQBePulledHigh(); + float avgTimer = 0.0f; + + ctBefore = read32(ARM_SYSTIMER_CLO); + + //resetWhileEmulating = false; + selectedViaIECCommands = false; + + u32 hash = pi1541.drive.GetDiskImage()->GetHash(); + // 0x42c02586 = maniac_mansion_s1[lucasfilm_1989](ntsc).g64 + // 0x18651422 = aliens[electric_dreams_1987].g64 + // 0x2a7f4b77 = zak_mckracken_boot[activision_1988](manual)(!).g64 + if (hash == 0x42c02586 || hash == 0x18651422 || hash == 0x2a7f4b77) + { + refreshOutsAfterCPUStep = false; + } + + while (cycleCount < FAST_BOOT_CYCLES) + { + m6502.Step(); + pi1541.Update(); + cycleCount++; + IEC_Bus::ReadEmulationMode1541(); + } + bool buttonState = false; + bool prevButtonState = false; + + while (true) + { + + if (m6502.SYNC()) // About to start a new instruction. + { + pc = m6502.GetPC(); + // See if the emulated cpu is executing CD:_ (ie back out of emulated image) + if (snoopIndex == 0 && (pc == SNOOP_CD_CBM || pc == SNOOP_CD_JIFFY_BOTH || pc == SNOOP_CD_JIFFY_DRIVEONLY)) snoopPC = pc; + + if (pc == snoopPC) + { + if (Snoop(m6502.GetA())) + { + return EXIT_CD; + } + } + } + + m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change + + if (refreshOutsAfterCPUStep) + IEC_Bus::RefreshOuts1541(); // Now output all outputs. + + IEC_Bus::OutputLED = pi1541.drive.IsLEDOn(); + if (IEC_Bus::OutputLED ^ oldLED) + { + SetACTLed(IEC_Bus::OutputLED); + oldLED = IEC_Bus::OutputLED; + } + + pi1541.Update(); + + if (__builtin_expect(IEC_Bus::IsReset(), false)) + resetCount++; + else + resetCount = 0; + + if ((resetCount > 10)) + { + return EXIT_RESET; + } + + buttonState = IEC_Bus::AnyButtonPressed(); + if (__builtin_expect(buttonState, false)) + { + IEC_Bus::ReadButtonsEmulationMode(); + inputMappings->CheckButtonsEmulationMode(); + if (numberOfImages > 1) + { + bool nextDisk = inputMappings->NextDisk(); + bool prevDisk = inputMappings->PrevDisk(); + if (nextDisk) + { + pi1541.drive.Insert(diskCaddy.PrevDisk()); + } + if (prevDisk) + { + pi1541.drive.Insert(diskCaddy.NextDisk()); + } + } + bool exitEmulation = inputMappings->Exit(); + if (exitEmulation) + return EXIT_KEYBOARD; + } + else if (__builtin_expect(!buttonState & prevButtonState, false)) + { + IEC_Bus::ReadButtonsEmulationMode(); + inputMappings->CheckButtonsEmulationMode(); + } + + prevButtonState = buttonState; + + do + { + ctAfter = read32(ARM_SYSTIMER_CLO); + } while (ctAfter == ctBefore); // Sync to the 1MHz clock + + + ctBefore = ctAfter; + IEC_Bus::ReadEmulationMode1541(); + + IEC_Bus::RefreshOuts1541(); // Now output all outputs. + } + return EXIT_UNKNOWN; +} + +#if not defined(EXPERIMENTALZERO) EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) { EXIT_TYPE exitReason = EXIT_UNKNOWN; @@ -891,6 +1050,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) return exitReason; } + EXIT_TYPE Emulate1581(FileBrowser* fileBrowser) { EXIT_TYPE exitReason = EXIT_UNKNOWN; @@ -1075,16 +1235,23 @@ EXIT_TYPE Emulate1581(FileBrowser* fileBrowser) } return exitReason; } +#endif void emulator() { +#if not defined(EXPERIMENTALZERO) Keyboard* keyboard = Keyboard::Instance(); +#endif FileBrowser* fileBrowser; EXIT_TYPE exitReason = EXIT_UNKNOWN; roms.lastManualSelectedROMIndex = 0; +#if defined(EXPERIMENTALZERO) + diskCaddy.SetScreen(); +#else diskCaddy.SetScreen(&screen, screenLCD); +#endif fileBrowser = new FileBrowser(inputMappings, &diskCaddy, &roms, &deviceID, options.DisplayPNGIcons(), &screen, screenLCD, options.ScrollHighlightRate()); fileBrowser->DisplayRoot(); pi1541.Initialise(); @@ -1095,7 +1262,6 @@ void emulator() m_IEC_Commands.SetNewDiskType(options.GetNewDiskType()); emulating = IEC_COMMANDS; - while (1) { if (emulating == IEC_COMMANDS) @@ -1124,8 +1290,9 @@ void emulator() selectedViaIECCommands = false; inputMappings->Reset(); +#if not defined(EXPERIMENTALZERO) inputMappings->SetKeyboardBrowseLCDScreen(screenLCD && options.KeyboardBrowseLCDScreen()); - +#endif fileBrowser->ShowDeviceAndROM(); if (!options.GetDisableSD2IECCommands()) @@ -1149,7 +1316,6 @@ void emulator() break; case IEC_Commands::NONE: fileBrowser->Update(); - // Check selections made via FileBrowser if (fileBrowser->SelectionsMade()) emulating = BeginEmulating(fileBrowser, fileBrowser->LastSelectionName()); @@ -1210,7 +1376,7 @@ void emulator() fileBrowser->ShowDeviceAndROM(); break; case IEC_Commands::DEVICE_SWITCHED: - DEBUG_LOG("DEVICE_SWITCHED\r\n"); + DEBUG_LOG("DECIVE_SWITCHED\r\n"); fileBrowser->DeviceSwitched(); break; default: @@ -1234,8 +1400,10 @@ void emulator() { if (emulating == EMULATING_1541) exitReason = Emulate1541(fileBrowser); +#if not defined(EXPERIMENTALZERO) else exitReason = Emulate1581(fileBrowser); +#endif DEBUG_LOG("Exited emulation\r\n"); @@ -1320,6 +1488,7 @@ static bool AttemptToLoadROM(char* ROMName) static void DisplayLogo() { +#if not defined(EXPERIMENTALZERO) int w; int h; int channels_in_file; @@ -1329,6 +1498,7 @@ static void DisplayLogo() snprintf(tempBuffer, tempBufferSize, "V%d.%02d", versionMajor, versionMinor); screen.PrintText(false, 20, 180, tempBuffer, FileBrowser::Colour(VIC2_COLOUR_INDEX_BLUE)); +#endif } static void LoadOptions() @@ -1354,6 +1524,7 @@ static void LoadOptions() void DisplayOptions(int y_pos) { +#if not defined(EXPERIMENTALZERO) // print confirmation of parsed options snprintf(tempBuffer, tempBufferSize, "ignoreReset = %d\r\n", options.IgnoreReset()); screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); @@ -1375,10 +1546,12 @@ void DisplayOptions(int y_pos) screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName()); screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); +#endif } void DisplayI2CScan(int y_pos) { +#if not defined(EXPERIMENTALZERO) int BSCMaster = options.I2CBusMaster(); snprintf(tempBuffer, tempBufferSize, "Scanning i2c bus %d ...\r\n", BSCMaster); @@ -1401,6 +1574,7 @@ void DisplayI2CScan(int y_pos) ptr += snprintf (tempBuffer+ptr, tempBufferSize-ptr, "Nothing"); screen.PrintText(false, 0, y_pos+16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); +#endif } static void CheckOptions() @@ -1522,6 +1696,7 @@ static void CheckOptions() } } + if (roms.ROMValid[0] == false && !(AttemptToLoadROM("d1541.rom") || AttemptToLoadROM("dos1541") || AttemptToLoadROM("d1541II") || AttemptToLoadROM("Jiffy.bin"))) { snprintf(tempBuffer, tempBufferSize, "No ROM file found!\r\nPlease copy a valid 1541 ROM file in the root folder of the SD card.\r\nThe file needs to be called 'dos1541'."); @@ -1563,6 +1738,7 @@ bool SwitchDrive(const char* drive) void UpdateFirmwareToSD() { +#if not defined(EXPERIMENTALZERO) const char* firmwareName = "kernel.img"; DIR dir; FILINFO filInfo; @@ -1658,10 +1834,12 @@ void UpdateFirmwareToSD() f_chdir(cwd); } } +#endif } void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour, u32 backgroundColour) { +#if not defined(EXPERIMENTALZERO) char buffer[256] = { 0 }; if (!LCD) @@ -1684,6 +1862,7 @@ void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour, core0RefreshingScreen.Release(); } +#endif } extern "C" @@ -1699,8 +1878,9 @@ extern "C" disk_setEMM(&m_EMMC); f_mount(&fileSystemSD, "SD:", 1); +#if not defined(EXPERIMENTALZERO) RPI_AuxMiniUartInit(115200, 8); - +#endif LoadOptions(); InitialiseHardware(); @@ -1712,7 +1892,7 @@ extern "C" DisplayLogo(); InitialiseLCD(); - +#if not defined(EXPERIMENTALZERO) int y_pos = 184; snprintf(tempBuffer, tempBufferSize, "Copyright(C) 2018 Stephen White"); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); @@ -1727,10 +1907,12 @@ extern "C" if (options.ShowOptions()) DisplayOptions(y_pos+=32); +#endif //if (!options.QuickBoot()) - // IEC_Bus::WaitMicroSeconds(3 * 1000000); + //IEC_Bus::WaitMicroSeconds(3 * 1000000); InterruptSystemInitialize(); +#if not defined(EXPERIMENTALZERO) TimerSystemInitialize(); USPiInitialize(); @@ -1752,6 +1934,7 @@ extern "C" // DEBUG_LOG("Mouse found\r\n"); keyboard = new Keyboard(); +#endif inputMappings = new InputMappings(); //USPiMouseRegisterStatusHandler(MouseHandler); @@ -1762,7 +1945,7 @@ extern "C" IEC_Bus::SetInvertIECInputs(options.InvertIECInputs()); IEC_Bus::SetInvertIECOutputs(options.InvertIECOutputs()); IEC_Bus::SetIgnoreReset(options.IgnoreReset()); - +#if not defined(EXPERIMENTALZERO) if (!options.SoundOnGPIO()) { dmaSound = (u32*)malloc(Sample_bin_size * 4); @@ -1786,7 +1969,7 @@ extern "C" if (SwitchDrive("USB01:")) UpdateFirmwareToSD(); } - +#endif f_chdir("/1541"); m_IEC_Commands.SetStarFileName(options.GetStarFileName()); @@ -1795,12 +1978,11 @@ extern "C" pi1541.drive.SetVIA(&pi1541.VIA[1]); pi1541.VIA[0].GetPortB()->SetPortOut(0, IEC_Bus::PortB_OnPortOut); - IEC_Bus::Initialise(); - +#if not defined(EXPERIMENTALZERO) if (screenLCD) screenLCD->ClearInit(0); - +#endif #ifdef HAS_MULTICORE start_core(3, _spin_core); start_core(2, _spin_core); diff --git a/src/options.h b/src/options.h index 0aa41fb..bafb5f1 100644 --- a/src/options.h +++ b/src/options.h @@ -63,7 +63,11 @@ public: inline unsigned int QuickBoot() const { return quickBoot; } inline unsigned int ShowOptions() const { return showOptions; } inline unsigned int DisplayPNGIcons() const { return displayPNGIcons; } +#if defined(EXPERIMENTALZERO) + inline unsigned int SoundOnGPIO() const { return false; } +#else inline unsigned int SoundOnGPIO() const { return soundOnGPIO; } +#endif inline unsigned int SoundOnGPIODuration() const { return soundOnGPIODuration; } inline unsigned int SoundOnGPIOFreq() const { return soundOnGPIOFreq; } inline unsigned int SplitIECLines() const { return splitIECLines; } From 1880a2c710afa8de22ca3f55ae051f6b5c1110cf Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Sun, 1 Sep 2019 13:46:29 +0200 Subject: [PATCH 2/8] Fixed a couple of incorrcet ifdefs.. Wrappped the experimental code correctly in main and fixed a comment typo in the inputmappings. --- src/InputMappings.h | 6 +++--- src/main.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/InputMappings.h b/src/InputMappings.h index d00714f..69977fa 100644 --- a/src/InputMappings.h +++ b/src/InputMappings.h @@ -121,17 +121,17 @@ public: #else inline bool Exit() { - return KeyboardFlag(ESC_FLAG) /*| UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG); + return KeyboardFlag(ESC_FLAG) | /*UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG); } inline bool NextDisk() { - return KeyboardFlag(NEXT_FLAG) /*| UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG); + return KeyboardFlag(NEXT_FLAG) | /*UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG); } inline bool PrevDisk() { - return KeyboardFlag(PREV_FLAG) /*| UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG); + return KeyboardFlag(PREV_FLAG) | /*UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG); } #endif inline bool AutoLoad() { return KeyboardFlag(AUTOLOAD_FLAG); } diff --git a/src/main.cpp b/src/main.cpp index f32312a..e925e01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -692,6 +692,7 @@ void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser) } } +#if defined(EXPERIMENTALZERO) EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) { bool oldLED = false; @@ -842,7 +843,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) return EXIT_UNKNOWN; } -#if not defined(EXPERIMENTALZERO) +#else EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) { EXIT_TYPE exitReason = EXIT_UNKNOWN; From bddc9a7d290ff0fb86ee459346c3208c7f73c1ce Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Sun, 1 Sep 2019 17:38:27 +0200 Subject: [PATCH 3/8] Save support added Optimized the DriveLoopWrite code. --- src/Drive.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Drive.cpp b/src/Drive.cpp index a7b2a28..060f431 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -651,11 +651,12 @@ void Drive::DriveLoopRead() void Drive::DriveLoopWrite() { - unsigned int minCycles; - unsigned int cycles = 0; - for (unsigned int cycles = 0; cycles != 16; ++cycles) + const unsigned int cycleStep = 16 - CLOCK_SEL_AB; + unsigned int cycles = 16 - UE7Counter; + while(cycles < 16) { - if (++UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. + //No check is required. This loops is all about the UE7Counter. + //if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. { UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. @@ -680,7 +681,15 @@ void Drive::DriveLoopWrite() SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. writeShiftRegister = m_pVIA->GetPortA()->GetOutput(); } + + if ((16-cycles) < cycleStep) + { + UE7Counter += 16 - cycles; + return; + } } + UE7Counter += cycleStep; + cycles += cycleStep; } } #endif \ No newline at end of file From 3978ef21651bae2251efb0bbb19a290cbb48c7b6 Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Tue, 3 Sep 2019 23:31:46 +0200 Subject: [PATCH 4/8] 1541 Drive speed improvements Specialized drive read loops for the most common cases, triggers a vast speed improvement in some scenarios. Improved saving speed. Removed some more code that's not really required right now. --- src/Drive.cpp | 268 ++++++++++++++++++++++++++++++++++++++++++------- src/Drive.h | 5 +- src/Pi1581.cpp | 4 + src/iec_bus.h | 4 +- src/main.cpp | 33 +++--- 5 files changed, 259 insertions(+), 55 deletions(-) diff --git a/src/Drive.cpp b/src/Drive.cpp index 060f431..91682c0 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -358,6 +358,7 @@ void Drive::Reset() #if defined(EXPERIMENTALZERO) LED = false; cyclesForBit = 0; + UE7Counter = 16; #endif headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz) @@ -568,20 +569,71 @@ bool Drive::Update() #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) -void Drive::DriveLoopRead() +void Drive::DriveLoopReadNoFluxNoCycles() +{ + unsigned int cycles = 16; + fluxReversalCyclesLeft -= 16; + cyclesLeftForBit -= 16; + while (true) + { + if (cycles < UE7Counter) + { + UE7Counter -= cycles; + cycles = 0; + return; + } + + cycles -= UE7Counter; + + UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. + ++UF4Counter &= 0xf; // Clock and clamp UF4. + // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) + // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) + if ((UF4Counter & 0x3) == 2) + { + readShiftRegister <<= 1; + readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + + writeShiftRegister <<= 1; + // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. + if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC + { + UE3Counter = 0; // Phase lock on to byte boundary + m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC + } + else + { + m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits + UE3Counter++; + } + } + // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 + else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary + { + UE3Counter = 0; + SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. + writeShiftRegister = (u8)(readShiftRegister & 0xff); + m_pVIA->GetPortA()->SetInput(writeShiftRegister); + } + }; +} + +void Drive::DriveLoopReadNoFlux() { unsigned int minCycles; - unsigned int cycles = 0; + unsigned int cycles = 16; + + fluxReversalCyclesLeft -= 16; while (true) { - minCycles = min(min(cyclesLeftForBit, fluxReversalCyclesLeft), 16 - max(UE7Counter, cycles)); + minCycles = min(min(cyclesLeftForBit, cycles), UE7Counter); cyclesLeftForBit -= minCycles; - fluxReversalCyclesLeft -= minCycles; - cycles += minCycles; - UE7Counter += minCycles; + cycles -= minCycles; + UE7Counter -= minCycles; - if (cycles == 16) + if (cycles == 0) return; if (cyclesLeftForBit == 0) @@ -605,14 +657,9 @@ void Drive::DriveLoopRead() } } - if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen + if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. { - ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one. - } - - if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. - { - UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. ++UF4Counter &= 0xf; // Clock and clamp UF4. // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) @@ -644,21 +691,32 @@ void Drive::DriveLoopRead() m_pVIA->GetPortA()->SetInput(writeShiftRegister); } } - - }; } - -void Drive::DriveLoopWrite() +void Drive::DriveLoopReadNoCycles() { - const unsigned int cycleStep = 16 - CLOCK_SEL_AB; - unsigned int cycles = 16 - UE7Counter; - while(cycles < 16) + unsigned int minCycles; + unsigned int cycles = 16; + + cyclesLeftForBit -= 16; + while (true) { - //No check is required. This loops is all about the UE7Counter. - //if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4. + minCycles = min(cycles, min(UE7Counter, fluxReversalCyclesLeft)); + fluxReversalCyclesLeft -= minCycles; + cycles -= minCycles; + UE7Counter -= minCycles; + + if (cycles == 0) + return; + + if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen { - UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one. + } + + if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. + { + UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. ++UF4Counter &= 0xf; // Clock and clamp UF4. // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) @@ -668,28 +726,166 @@ void Drive::DriveLoopWrite() readShiftRegister <<= 1; readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) - SetNextBit((writeShiftRegister & 0x80)); - writeShiftRegister <<= 1; // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. - UE3Counter++; + if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC + { + UE3Counter = 0; // Phase lock on to byte boundary + m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC + } + else + { + m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits + UE3Counter++; + } } // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary { UE3Counter = 0; SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. - writeShiftRegister = m_pVIA->GetPortA()->GetOutput(); - } - - if ((16-cycles) < cycleStep) - { - UE7Counter += 16 - cycles; - return; + writeShiftRegister = (u8)(readShiftRegister & 0xff); + m_pVIA->GetPortA()->SetInput(writeShiftRegister); } } - UE7Counter += cycleStep; - cycles += cycleStep; + }; +} +void Drive::DriveLoopRead() +{ + + if (fluxReversalCyclesLeft > 16 && cyclesLeftForBit > 16) + { + DriveLoopReadNoFluxNoCycles(); + return; + } + + if (fluxReversalCyclesLeft > 16) + { + DriveLoopReadNoFlux(); + return; + } + + if (cyclesLeftForBit > 16) + { + DriveLoopReadNoCycles(); + return; + } + + unsigned int minCycles; + unsigned int cycles = 16; + + while (true) + { + minCycles = min(min(cyclesLeftForBit, cycles), min(UE7Counter, fluxReversalCyclesLeft)); + cyclesLeftForBit -= minCycles; + fluxReversalCyclesLeft -= minCycles; + cycles -= minCycles; + UE7Counter -= minCycles; + + if (cycles == 0) + return; + + if (cyclesLeftForBit == 0) + { + //which is faster? single loop ceil check or the 3 lines below? + float fn = 2.0f * cyclesPerBit - cyclesForBit; + cyclesLeftForBit = (int)fn; + cyclesForBit = cyclesPerBit; + if (fn != (float)cyclesLeftForBit) { + ++cyclesLeftForBit; + ++cyclesForBit; + } + + //cyclesForBit -= cyclesPerBit; + //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); + //cyclesForBit += cyclesLeftForBit; + + if (GetNextBit()) + { + ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); + } + } + + if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen + { + ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one. + } + + if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. + { + UE7Counter = 16-CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. + ++UF4Counter &= 0xf; // Clock and clamp UF4. + // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) + // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) + //if ((UF4Counter & 0x3) == 2) + if (UF4Counter == 2 || UF4Counter == 6) //You'd think the bit operation should be faster... + { + readShiftRegister <<= 1; + readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + + writeShiftRegister <<= 1; + // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. + if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC + { + UE3Counter = 0; // Phase lock on to byte boundary + m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC + } + else + { + m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits + UE3Counter++; + } + } + // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 + else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary + { + UE3Counter = 0; + SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. + writeShiftRegister = (u8)(readShiftRegister & 0xff); + m_pVIA->GetPortA()->SetInput(writeShiftRegister); + } + } + }; +} + +void Drive::DriveLoopWrite() +{ + unsigned int cycles = 16; + while(true) + { + if (cycles < UE7Counter) + { + UE7Counter -= cycles; + cycles = 0; + return; + } + + cycles -= UE7Counter; + + UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. + // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. + ++UF4Counter &= 0xf; // Clock and clamp UF4. + // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) + // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) + if ((UF4Counter & 0x3) == 2) + { + readShiftRegister <<= 1; + readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + + SetNextBit((writeShiftRegister & 0x80)); + + writeShiftRegister <<= 1; + // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. + UE3Counter++; + } + // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 + else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary + { + UE3Counter = 0; + SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. + writeShiftRegister = m_pVIA->GetPortA()->GetOutput(); + } } } #endif \ No newline at end of file diff --git a/src/Drive.h b/src/Drive.h index 3d15553..a3f5498 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -51,6 +51,9 @@ public: #if defined(EXPERIMENTALZERO) void DriveLoopWrite(); void DriveLoopRead(); + void DriveLoopReadNoFluxNoCycles(); + void DriveLoopReadNoFlux(); + void DriveLoopReadNoCycles(); #endif void Insert(DiskImage* diskImage); @@ -69,7 +72,7 @@ private: int32_t localSeed; inline void ResetEncoderDecoder(unsigned int min, unsigned int /*max*/span) { - UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) + UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) UF4Counter = 0; localSeed = ((localSeed * 1103515245) + 12345) & 0x7fffffff; fluxReversalCyclesLeft = (span) * (localSeed >> 11) + min; diff --git a/src/Pi1581.cpp b/src/Pi1581.cpp index a581e26..ff2b068 100644 --- a/src/Pi1581.cpp +++ b/src/Pi1581.cpp @@ -93,6 +93,7 @@ extern u16 pc; u8 read6502_1581(u16 address) { u8 value = 0; +#if not defined(EXPERIMENTALZERO) if (address & 0x8000) { value = roms.Read1581(address); @@ -115,6 +116,7 @@ u8 read6502_1581(u16 address) { value = address >> 8; // Empty address bus } +#endif return value; } @@ -127,6 +129,7 @@ u8 peek6502_1581(u16 address) void write6502_1581(u16 address, const u8 value) { +#if not defined(EXPERIMENTALZERO) if (address & 0x8000) { return; @@ -145,6 +148,7 @@ void write6502_1581(u16 address, const u8 value) { s_u8Memory[address & 0x1fff] = value; } +#endif } static void CIAPortA_OnPortOut(void* pUserData, unsigned char status) diff --git a/src/iec_bus.h b/src/iec_bus.h index 553b5e0..b6eb057 100644 --- a/src/iec_bus.h +++ b/src/iec_bus.h @@ -277,7 +277,7 @@ public: RPI_SetGpioPinFunction((rpi_gpio_pin_t)PIGPIO_OUT_SRQ, FS_OUTPUT); } - +#if not defined(EXPERIMENTALZERO) // Set up audio. write32(CM_PWMDIV, CM_PASSWORD + 0x2000); write32(CM_PWMCTL, CM_PASSWORD + CM_ENAB + CM_SRC_OSCILLATOR); // Use Default 100MHz Clock @@ -285,7 +285,7 @@ public: write32(PWM_RNG1, 0x1B4); // 8bit 44100Hz Mono write32(PWM_RNG2, 0x1B4); write32(PWM_CTL, PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1); - +#endif int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned); for (index = 0; index < buttonCount; ++index) diff --git a/src/main.cpp b/src/main.cpp index e925e01..a601855 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,7 +101,9 @@ u8 s_u8Memory[0xc000]; int numberOfUSBMassStorageDevices = 0; DiskCaddy diskCaddy; Pi1541 pi1541; +#if not defined(EXPERIMENTALZERO) Pi1581 pi1581; +#endif CEMMCDevice m_EMMC; Screen screen; ScreenLCD* screenLCD = 0; @@ -118,8 +120,9 @@ bool USBKeyboardDetected = false; bool selectedViaIECCommands = false; u16 pc; +#if not defined(EXPERIMENTALZERO) SpinLock core0RefreshingScreen; - +#endif unsigned int screenWidth = 1024; unsigned int screenHeight = 768; @@ -609,6 +612,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc DiskImage* diskImage = diskCaddy.SelectFirstImage(); if (diskImage) { +#if not defined(EXPERIMENTALZERO) if (diskImage->IsD81()) { pi1581.Insert(diskImage); @@ -617,6 +621,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc return EMULATING_1581; } else +#endif { pi1541.drive.Insert(diskImage); fileBrowser->DisplayDiskInfo(diskImage, filenameForIcon); @@ -668,7 +673,9 @@ void GlobalSetDeviceID(u8 id) deviceID = id; m_IEC_Commands.SetDeviceId(id); pi1541.SetDeviceID(id); +#if not defined(EXPERIMENTALZERO) pi1581.SetDeviceID(id); +#endif } void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser) @@ -712,10 +719,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) if (numberOfImagesMax > 10) numberOfImagesMax = 10; - core0RefreshingScreen.Acquire(); - diskCaddy.Display(); - core0RefreshingScreen.Release(); - inputMappings->directDiskSwapRequest = 0; // Force an update on all the buttons now before we start emulation mode. IEC_Bus::ReadBrowseMode(); @@ -731,8 +734,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) pi1541.Reset(); // will call IEC_Bus::Reset(); IEC_Bus::OutputLED = false; IEC_Bus::LetSRQBePulledHigh(); - float avgTimer = 0.0f; - ctBefore = read32(ARM_SYSTIMER_CLO); //resetWhileEmulating = false; @@ -756,7 +757,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } bool buttonState = false; bool prevButtonState = false; - while (true) { @@ -776,7 +776,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change - + if (refreshOutsAfterCPUStep) IEC_Bus::RefreshOuts1541(); // Now output all outputs. @@ -829,13 +829,13 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) prevButtonState = buttonState; - do + do { ctAfter = read32(ARM_SYSTIMER_CLO); } while (ctAfter == ctBefore); // Sync to the 1MHz clock - ctBefore = ctAfter; + ctBefore = ctAfter; IEC_Bus::ReadEmulationMode1541(); IEC_Bus::RefreshOuts1541(); // Now output all outputs. @@ -1274,8 +1274,9 @@ void emulator() IEC_Bus::Reset(); IEC_Bus::LetSRQBePulledHigh(); - +#if not defined(EXPERIMENTALZERO) core0RefreshingScreen.Acquire(); +#endif IEC_Bus::WaitMicroSeconds(100); roms.ResetCurrentROMIndex(); @@ -1285,9 +1286,9 @@ void emulator() fileBrowser->ClearSelections(); fileBrowser->RefeshDisplay(); // Just redisplay the current folder. - +#if not defined(EXPERIMENTALZERO) core0RefreshingScreen.Release(); - +#endif selectedViaIECCommands = false; inputMappings->Reset(); @@ -1590,7 +1591,7 @@ static void CheckOptions() deviceID = (u8)options.GetDeviceID(); DEBUG_LOG("DeviceID = %d\r\n", deviceID); - +#if not defined(EXPERIMENTALZERO) const char* FontROMName = options.GetRomFontName(); if (FontROMName) { @@ -1625,7 +1626,7 @@ static void CheckOptions() //DEBUG_LOG("Read ROM %s from options\r\n", ROMName); } } - +#endif const char* ROMName1581 = options.GetRomName1581(); if (ROMName1581) { From 2d538e4975f28e378ab1261f2f614ebfac917014 Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Wed, 4 Sep 2019 22:06:21 +0200 Subject: [PATCH 5/8] Some code restructing and removed writeshiftregister use. Moved the branching to Update. writeShiftRegister renamed. Fixed typo in main drive read. Reorganised SetInput call try to trigger conditionals. --- src/Drive.cpp | 119 +++++++++++++++++++++----------------------------- src/Drive.h | 3 +- 2 files changed, 51 insertions(+), 71 deletions(-) diff --git a/src/Drive.cpp b/src/Drive.cpp index 91682c0..b16ae4a 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -473,7 +473,22 @@ bool Drive::Update() if (writing) DriveLoopWrite(); else - DriveLoopRead(); + { + if (fluxReversalCyclesLeft > 16 && cyclesLeftForBit > 16) + { + DriveLoopReadNoFluxNoCycles(); + } + else if (fluxReversalCyclesLeft > 16) + { + DriveLoopReadNoFlux(); + } + else if (cyclesLeftForBit > 16) + { + DriveLoopReadNoCycles(); + } + else + DriveLoopRead(); + } #else for (int cycles = 0; cycles < 16; ++cycles) { @@ -593,28 +608,24 @@ void Drive::DriveLoopReadNoFluxNoCycles() if ((UF4Counter & 0x3) == 2) { readShiftRegister <<= 1; - readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + readShiftRegister |= (UF4Counter == 2); - writeShiftRegister <<= 1; - // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. - if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC - { + //writeShiftRegister <<= 1; + + bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff); + m_pVIA->GetPortB()->SetInput(0x80, !resetTime); + if (resetTime) // if the last 10 bits are 1s then SYNC UE3Counter = 0; // Phase lock on to byte boundary - m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC - } else - { - m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits UE3Counter++; - } } // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary { UE3Counter = 0; SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. - writeShiftRegister = (u8)(readShiftRegister & 0xff); - m_pVIA->GetPortA()->SetInput(writeShiftRegister); +// writeShiftRegister = readShiftRegister; + m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff); } }; } @@ -667,28 +678,24 @@ void Drive::DriveLoopReadNoFlux() if ((UF4Counter & 0x3) == 2) { readShiftRegister <<= 1; - readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + readShiftRegister |= (UF4Counter == 2); - writeShiftRegister <<= 1; - // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. - if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC - { + //writeShiftRegister <<= 1; + + bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff); + m_pVIA->GetPortB()->SetInput(0x80, !resetTime); + if (resetTime) // if the last 10 bits are 1s then SYNC UE3Counter = 0; // Phase lock on to byte boundary - m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC - } else - { - m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits UE3Counter++; - } } // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary { UE3Counter = 0; SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. - writeShiftRegister = (u8)(readShiftRegister & 0xff); - m_pVIA->GetPortA()->SetInput(writeShiftRegister); + // writeShiftRegister = readShiftRegister; + m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff); } } }; @@ -724,53 +731,30 @@ void Drive::DriveLoopReadNoCycles() if ((UF4Counter & 0x3) == 2) { readShiftRegister <<= 1; - readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + readShiftRegister |= (UF4Counter == 2); - writeShiftRegister <<= 1; - // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. - if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC - { + //writeShiftRegister <<= 1; + + bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff); + m_pVIA->GetPortB()->SetInput(0x80, !resetTime); + if (resetTime) // if the last 10 bits are 1s then SYNC UE3Counter = 0; // Phase lock on to byte boundary - m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC - } else - { - m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits UE3Counter++; - } } // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary { UE3Counter = 0; SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. - writeShiftRegister = (u8)(readShiftRegister & 0xff); - m_pVIA->GetPortA()->SetInput(writeShiftRegister); + // writeShiftRegister = readShiftRegister; + m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff); } } }; } void Drive::DriveLoopRead() { - - if (fluxReversalCyclesLeft > 16 && cyclesLeftForBit > 16) - { - DriveLoopReadNoFluxNoCycles(); - return; - } - - if (fluxReversalCyclesLeft > 16) - { - DriveLoopReadNoFlux(); - return; - } - - if (cyclesLeftForBit > 16) - { - DriveLoopReadNoCycles(); - return; - } - unsigned int minCycles; unsigned int cycles = 16; @@ -818,32 +802,27 @@ void Drive::DriveLoopRead() ++UF4Counter &= 0xf; // Clock and clamp UF4. // The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock)) // - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0) - //if ((UF4Counter & 0x3) == 2) - if (UF4Counter == 2 || UF4Counter == 6) //You'd think the bit operation should be faster... + if ((UF4Counter & 0x3) == 2) { readShiftRegister <<= 1; - readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell) + readShiftRegister |= (UF4Counter == 2); - writeShiftRegister <<= 1; - // Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs. - if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC - { + //writeShiftRegister <<= 1; + + bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff); + m_pVIA->GetPortB()->SetInput(0x80, !resetTime); + if (resetTime) // if the last 10 bits are 1s then SYNC UE3Counter = 0; // Phase lock on to byte boundary - m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC - } else - { - m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits UE3Counter++; - } } // UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13 else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary { UE3Counter = 0; SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not. - writeShiftRegister = (u8)(readShiftRegister & 0xff); - m_pVIA->GetPortA()->SetInput(writeShiftRegister); + // writeShiftRegister = readShiftRegister; + m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff); } } }; diff --git a/src/Drive.h b/src/Drive.h index a3f5498..6713ee4 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -166,8 +166,10 @@ private: unsigned int cyclesLeftForBit; unsigned int fluxReversalCyclesLeft; unsigned int UE7Counter; + u32 writeShiftRegister; #else int UE7Counter; + u8 writeShiftRegister; #endif float cyclesForBit; u32 readShiftRegister; @@ -183,6 +185,5 @@ private: float cyclesPerBit; bool motor; bool LED; - u8 writeShiftRegister; }; #endif From 8875c55c251bf68c49acf212a04857180bb16e4c Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Sat, 7 Sep 2019 14:27:32 +0200 Subject: [PATCH 6/8] Fixed incorrect cycle calculation and removed floats entirely in drive loop Replace incorrect cyclesLeft calculation with faster non-floating point error calculator. Replaced modulo calculation with faster size comparison. --- src/Drive.cpp | 23 +++++++---------------- src/Drive.h | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Drive.cpp b/src/Drive.cpp index b16ae4a..bd3ccd6 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -487,7 +487,9 @@ bool Drive::Update() DriveLoopReadNoCycles(); } else + { DriveLoopRead(); + } } #else for (int cycles = 0; cycles < 16; ++cycles) @@ -580,6 +582,7 @@ bool Drive::Update() return dataReady; } + #if defined(EXPERIMENTALZERO) #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) @@ -597,7 +600,6 @@ void Drive::DriveLoopReadNoFluxNoCycles() cycles = 0; return; } - cycles -= UE7Counter; UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. @@ -649,14 +651,8 @@ void Drive::DriveLoopReadNoFlux() if (cyclesLeftForBit == 0) { - //which is faster? single loop ceil check or the 3 lines below? - float fn = 2.0f * cyclesPerBit - cyclesForBit; - cyclesLeftForBit = (int)fn; - cyclesForBit = cyclesPerBit; - if (fn != (float)cyclesLeftForBit) { - ++cyclesLeftForBit; - ++cyclesForBit; - } + cyclesForBitErrorCounter -= cyclesPerBitErrorConstant; + cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant); //cyclesForBit -= cyclesPerBit; //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); @@ -772,13 +768,8 @@ void Drive::DriveLoopRead() if (cyclesLeftForBit == 0) { //which is faster? single loop ceil check or the 3 lines below? - float fn = 2.0f * cyclesPerBit - cyclesForBit; - cyclesLeftForBit = (int)fn; - cyclesForBit = cyclesPerBit; - if (fn != (float)cyclesLeftForBit) { - ++cyclesLeftForBit; - ++cyclesForBit; - } + cyclesForBitErrorCounter -= cyclesPerBitErrorConstant; + cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant); //cyclesForBit -= cyclesPerBit; //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); diff --git a/src/Drive.h b/src/Drive.h index 6713ee4..1ad0933 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -96,6 +96,12 @@ private: bitsInTrack = diskImage->BitsInTrack(headTrackPos); headBitOffset %= bitsInTrack; cyclesPerBit = CYCLES_16Mhz_PER_ROTATION / (float)bitsInTrack; +#if defined(EXPERIMENTALZERO) + cyclesPerBitInt = cyclesPerBit; + cyclesPerBitErrorConstant = (unsigned int)((cyclesPerBit - ((float)cyclesPerBitInt)) * static_cast(0xffffffff)); + cyclesForBitErrorCounter = (unsigned int)(((cyclesForBit)-(int)(cyclesForBit)) * static_cast(0xffffffff)); +#endif + } inline void MoveHead(unsigned char headDirection) @@ -118,6 +124,15 @@ private: void DumpTrack(unsigned track); // Used for debugging disk images. +#if defined(EXPERIMENTALZERO) + inline u32 AdvanceSectorPositionR(int& byteOffset) + { + if (++headBitOffset == bitsInTrack) + headBitOffset = 0; + byteOffset = headBitOffset >> 3; + return (~headBitOffset) & 7; + } +#else // No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data. inline u32 AdvanceSectorPositionR(int& byteOffset) { @@ -125,7 +140,7 @@ private: byteOffset = headBitOffset >> 3; return (~headBitOffset) & 7; } - +#endif inline u32 AdvanceSectorPositionW(int& byteOffset) { byteOffset = headBitOffset >> 3; @@ -167,6 +182,9 @@ private: unsigned int fluxReversalCyclesLeft; unsigned int UE7Counter; u32 writeShiftRegister; + unsigned int cyclesForBitErrorCounter; + unsigned int cyclesPerBitErrorConstant; + unsigned int cyclesPerBitInt; #else int UE7Counter; u8 writeShiftRegister; From 9b38fc6d32f67cbcb490b86d27f71c161cd41e0a Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Tue, 10 Sep 2019 23:14:34 +0200 Subject: [PATCH 7/8] Early bail-out of DriveLoopReadNoFlux A couple of small optimizations that shouldn't make a difference but do such as: Addressing tracks as a single array. Caching a single byte instead of re-reading the array. (Note that caching 32bits did not improve but actually worsen things). Harsher interrupt disabling. Whitespace changes in main... Plus, early bail out from DriveLoopReadNoFlux. --- src/DiskImage.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++ src/DiskImage.h | 34 ++++++++++++++++++++++++++++++++ src/Drive.cpp | 16 ++++++++++------ src/Drive.h | 16 ++++++++++++++-- src/interrupt.c | 4 +++- src/interrupt.h | 2 +- src/main.cpp | 9 ++++++--- 7 files changed, 117 insertions(+), 13 deletions(-) diff --git a/src/DiskImage.cpp b/src/DiskImage.cpp index 10cbc63..e9ba652 100644 --- a/src/DiskImage.cpp +++ b/src/DiskImage.cpp @@ -151,7 +151,12 @@ void DiskImage::Close() void DiskImage::DumpTrack(unsigned track) { + +#if defined(EXPERIMENTALZERO) + unsigned char* src = &tracks[track << 13]; +#else unsigned char* src = tracks[track]; +#endif unsigned trackLength = trackLengths[track]; DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength); for (unsigned index = 0; index < trackLength; ++index) @@ -205,7 +210,11 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex) { unsigned char track = (halfTrackIndex >> 1); +#if defined(EXPERIMENTALZERO) + unsigned char* dest = &tracks[halfTrackIndex << 13]; +#else unsigned char* dest = tracks[halfTrackIndex]; +#endif trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH; @@ -800,7 +809,11 @@ bool DiskImage::OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsig //DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset); trackData += 2; trackLengths[track] = trackLength; +#if defined(EXPERIMENTALZERO) + memcpy(&tracks[track << 13], trackData, trackLength); +#else memcpy(tracks[track], trackData, trackLength); +#endif trackUsed[track] = true; //DEBUG_LOG("%d has data\r\n", track); } @@ -899,7 +912,11 @@ bool DiskImage::WriteG64(char* name) gcr_track[0] = (BYTE)(track_len % 256); gcr_track[1] = (BYTE)(track_len / 256); +#if defined(EXPERIMENTALZERO) + memcpy(buffer, &tracks[track << 13], track_len); +#else memcpy(buffer, tracks[track], track_len); +#endif memcpy(gcr_track + 2, buffer, track_len); bytesToWrite = G64_TRACK_MAXLEN + 2; @@ -965,11 +982,19 @@ bool DiskImage::OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsig unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100; int align; +#if defined(EXPERIMENTALZERO) + trackLengths[track] = extract_GCR_track(&tracks[track << 13], nibdata, &align + //, ALIGN_GAP + , ALIGN_NONE + , capacity_min[trackDensity[track]], + capacity_max[trackDensity[track]]); +#else trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align //, ALIGN_GAP , ALIGN_NONE , capacity_min[trackDensity[track]], capacity_max[trackDensity[track]]); +#endif trackUsed[track] = true; @@ -1031,7 +1056,11 @@ bool DiskImage::WriteNIB() { if (trackUsed[track]) { +#if defined(EXPERIMENTALZERO) + if (f_write(&fp, &tracks[track << 13], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten) +#else if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten) +#endif { DEBUG_LOG("Cannot write track data.\r\n"); } @@ -1250,10 +1279,18 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in unsigned char gcr[5]; unsigned char byte; unsigned char* offset; +#if defined(EXPERIMENTALZERO) + unsigned char* end = &tracks[track << 13] + trackLengths[track]; +#else unsigned char* end = tracks[track] + trackLengths[track]; +#endif shift = bitIndex & 7; +#if defined(EXPERIMENTALZERO) + offset = &tracks[track << 13] + (bitIndex >> 3); +#else offset = tracks[track] + (bitIndex >> 3); +#endif byte = offset[0] << shift; for (i = 0; i < num; i++, buf += 4) @@ -1262,7 +1299,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in { offset++; if (offset >= end) +#if defined(EXPERIMENTALZERO) + offset = &tracks[track << 13]; +#else offset = tracks[track]; +#endif if (shift) { @@ -1282,7 +1323,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex) { int readShiftRegister = 0; +#if defined(EXPERIMENTALZERO) + unsigned char byte = tracks[(track << 13) + (bitIndex >> 3)] << (bitIndex & 7); +#else unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7); +#endif bool prevBitZero = true; while (maxBits--) @@ -1314,7 +1359,11 @@ int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStar bitIndex++; if (bitIndex >= MAX_TRACK_LENGTH * 8) bitIndex = 0; +#if defined(EXPERIMENTALZERO) + byte = tracks[(track << 13)+(bitIndex >> 3)]; +#else byte = tracks[track][bitIndex >> 3]; +#endif } } return -1; diff --git a/src/DiskImage.h b/src/DiskImage.h index 42a2a7a..5dc3adf 100644 --- a/src/DiskImage.h +++ b/src/DiskImage.h @@ -78,19 +78,48 @@ public: bool GetDecodedSector(u32 track, u32 sector, u8* buffer); + inline unsigned char GetNextByte(u32 track, u32 byte) + { +#if defined(EXPERIMENTALZERO) + return tracks[(track << 13) + byte]; +#else + return tracks[track][byte]; +#endif + } + + inline bool GetNextBit(u32 track, u32 byte, u32 bit) { //if (attachedImageSize == 0) // return 0; +#if defined(EXPERIMENTALZERO) + return ((tracks[(track << 13) + byte] >> bit) & 1) != 0; +#else return ((tracks[track][byte] >> bit) & 1) != 0; +#endif } + inline void SetBit(u32 track, u32 byte, u32 bit, bool value) { if (attachedImageSize == 0) return; +#if defined(EXPERIMENTALZERO) + u8 dataOld = tracks[(track << 13) + byte]; + u8 bitMask = 1 << bit; + if (value) + { + TestDirty(track, (dataOld & bitMask) == 0); + tracks[(track << 13) + byte] |= bitMask; + } + else + { + TestDirty(track, (dataOld & bitMask) != 0); + tracks[(track << 13) + byte] &= bitMask; + } +#else u8 dataOld = tracks[track][byte]; u8 bitMask = 1 << bit; if (value) @@ -103,6 +132,7 @@ public: TestDirty(track, (dataOld & bitMask) != 0); tracks[track][byte] &= ~bitMask; } +#endif } static const unsigned char SectorsPerTrack[42]; @@ -160,7 +190,11 @@ public: union { +#if defined(EXPERIMENTALZERO) + unsigned char tracks[HALF_TRACK_COUNT * MAX_TRACK_LENGTH]; +#else unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH]; +#endif unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH]; }; diff --git a/src/Drive.cpp b/src/Drive.cpp index bd3ccd6..e121e49 100644 --- a/src/Drive.cpp +++ b/src/Drive.cpp @@ -662,9 +662,17 @@ void Drive::DriveLoopReadNoFlux() { ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); } + if (cycles < UE7Counter) + { + UE7Counter -= cycles; + cyclesLeftForBit -= cycles; + return; + } + cyclesLeftForBit -= UE7Counter; + cycles -= UE7Counter; } - if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. + //if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4. { UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings. // The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output. @@ -749,6 +757,7 @@ void Drive::DriveLoopReadNoCycles() } }; } + void Drive::DriveLoopRead() { unsigned int minCycles; @@ -767,14 +776,9 @@ void Drive::DriveLoopRead() if (cyclesLeftForBit == 0) { - //which is faster? single loop ceil check or the 3 lines below? cyclesForBitErrorCounter -= cyclesPerBitErrorConstant; cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant); - //cyclesForBit -= cyclesPerBit; - //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); - //cyclesForBit += cyclesLeftForBit; - if (GetNextBit()) { ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16); diff --git a/src/Drive.h b/src/Drive.h index 1ad0933..00646f5 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -148,12 +148,24 @@ private: ++headBitOffset %= bitsInTrack; return bit; } - + unsigned cachedheadTrackPos = -1; + int cachedbyteOffset = -1; + unsigned char cachedByte = 0; inline bool GetNextBit() { int byteOffset; int bit = AdvanceSectorPositionR(byteOffset); - return diskImage->GetNextBit(headTrackPos, byteOffset, bit); + + //Why is it faster to check both conditions here than to update the cache when moving the head? + if (byteOffset != cachedbyteOffset || cachedheadTrackPos != headTrackPos) + { + cachedByte = diskImage->GetNextByte(headTrackPos, byteOffset); + cachedbyteOffset = byteOffset; + cachedheadTrackPos = headTrackPos; + + } + return ((cachedByte >> bit) & 1) != 0; + //return diskImage->GetNextBit(headTrackPos, byteOffset, bit); } inline void SetNextBit(bool value) diff --git a/src/interrupt.c b/src/interrupt.c index dc8c793..ad5fa08 100644 --- a/src/interrupt.c +++ b/src/interrupt.c @@ -39,7 +39,9 @@ void InterruptSystemInitialize() write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2)); DataMemBarrier(); -#ifndef EXPERIMENTALZERO +#ifdef EXPERIMENTALZERO + DisableInterrupts(); +#else EnableInterrupts(); #endif } diff --git a/src/interrupt.h b/src/interrupt.h index 0dcfb93..f917ddd 100644 --- a/src/interrupt.h +++ b/src/interrupt.h @@ -9,7 +9,7 @@ extern "C" { #include "bcm2835int.h" #define EnableInterrupts() __asm volatile ("cpsie i") -#define DisableInterrupts() __asm volatile ("cpsid i") +#define DisableInterrupts() __asm volatile ("cpsid ifa, #0x13") typedef void IRQHandler(void* param); diff --git a/src/main.cpp b/src/main.cpp index a601855..91bc238 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -776,7 +776,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change - + if (refreshOutsAfterCPUStep) IEC_Bus::RefreshOuts1541(); // Now output all outputs. @@ -829,16 +829,19 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) prevButtonState = buttonState; - do + do { ctAfter = read32(ARM_SYSTIMER_CLO); - } while (ctAfter == ctBefore); // Sync to the 1MHz clock + } while (ctAfter == ctBefore); // Sync to the 1MHz clock ctBefore = ctAfter; IEC_Bus::ReadEmulationMode1541(); IEC_Bus::RefreshOuts1541(); // Now output all outputs. + + + } return EXIT_UNKNOWN; } From 58be6a8079faa29a8e7b9b7e36397364d4fe04c5 Mon Sep 17 00:00:00 2001 From: Alexander Martinelle Date: Sat, 21 Sep 2019 17:24:09 +0200 Subject: [PATCH 8/8] OLED support added OLED support added back in with extra update call to refresh the display on single core devices. New macro added to allow 1581 tests in the Pi Zero experimental build. --- src/DiskCaddy.cpp | 18 ++++++++--------- src/DiskCaddy.h | 18 +++++++++++------ src/FileBrowser.cpp | 49 +++++++++++---------------------------------- src/FileBrowser.h | 10 +-------- src/InputMappings.h | 6 +++--- src/Pi1581.cpp | 4 ++-- src/defs.h | 4 +++- src/main.cpp | 30 ++++++++++++++------------- 8 files changed, 58 insertions(+), 81 deletions(-) diff --git a/src/DiskCaddy.cpp b/src/DiskCaddy.cpp index 1954106..2cc9781 100644 --- a/src/DiskCaddy.cpp +++ b/src/DiskCaddy.cpp @@ -53,7 +53,7 @@ bool DiskCaddy::Empty() snprintf(buffer, 256, "Saving %s\r\n", disks[index].GetName()); screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); } - +#endif if (screenLCD) { RGBA BkColour = RGBA(0, 0, 0, 0xFF); @@ -68,7 +68,6 @@ bool DiskCaddy::Empty() screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } -#endif } disks[index].Close(); } @@ -84,7 +83,7 @@ bool DiskCaddy::Empty() snprintf(buffer, 256, "Saving Complete \r\n"); screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); } - +#endif if (screenLCD) { RGBA BkColour = RGBA(0, 0, 0, 0xFF); @@ -99,7 +98,6 @@ bool DiskCaddy::Empty() screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } -#endif } disks.clear(); @@ -125,6 +123,7 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly) snprintf(buffer, 256, "Loading %s\r\n", fileInfo->fname); screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); } +#endif if (screenLCD) { @@ -140,7 +139,6 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly) screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red); screenLCD->SwapBuffers(); } -#endif u32 bytesRead; SetACTLed(true); f_read(&fp, DiskImage::readBuffer, READBUFFER_SIZE, &bytesRead); @@ -303,6 +301,8 @@ void DiskCaddy::ShowSelectedImage(u32 index) snprintf(buffer, 256, "*"); screen->PrintText(false, x, y, buffer, white, red); } +#endif + if (screenLCD) { unsigned numberOfImages = GetNumberOfImages(); @@ -351,7 +351,6 @@ void DiskCaddy::ShowSelectedImage(u32 index) } screenLCD->SwapBuffers(); } -#endif } bool DiskCaddy::Update() @@ -368,15 +367,16 @@ bool DiskCaddy::Update() y = screen->ScaleY(screenPosYCaddySelections) + 16 + 16 * oldCaddyIndex; snprintf(buffer, 256, " "); screen->PrintText(false, x, y, buffer, red, red); - oldCaddyIndex = caddyIndex; - ShowSelectedImage(oldCaddyIndex); } +#endif + + oldCaddyIndex = caddyIndex; + ShowSelectedImage(oldCaddyIndex); if (screenLCD) { } -#endif return true; } return false; diff --git a/src/DiskCaddy.h b/src/DiskCaddy.h index fb86de4..b59247b 100644 --- a/src/DiskCaddy.h +++ b/src/DiskCaddy.h @@ -30,15 +30,17 @@ public: : selectedIndex(0) #if not defined(EXPERIMENTALZERO) , screen(0) - , screenLCD(0) #endif + , screenLCD(0) { } -#if defined(EXPERIMENTALZERO) - void SetScreen() { } -#else - void SetScreen(Screen* screen, ScreenBase* screenLCD) { this->screen = screen; this->screenLCD = screenLCD; } + void SetScreen(Screen* screen, ScreenBase* screenLCD) + { +#if not defined(EXPERIMENTALZERO) + this->screen = screen; #endif + this->screenLCD = screenLCD; + } bool Empty(); @@ -46,6 +48,9 @@ public: DiskImage* GetCurrentDisk() { +#if defined(EXPERIMENTALZERO) + Update(); +#endif if (selectedIndex < disks.size()) return &disks[selectedIndex]; @@ -55,6 +60,7 @@ public: DiskImage* NextDisk() { selectedIndex = (selectedIndex + 1) % (u32)disks.size(); + auto ret = GetCurrentDisk(); return GetCurrentDisk(); } @@ -108,8 +114,8 @@ private: u32 oldCaddyIndex; #if not defined(EXPERIMENTALZERO) ScreenBase* screen; - ScreenBase* screenLCD; #endif + ScreenBase* screenLCD; }; #endif \ No newline at end of file diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index 9eb6969..b14c186 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -82,7 +82,6 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b if (entryIndex < list->entries.size()) { FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex]; -#if not defined(EXPERIMENTALZERO) if (screen->IsLCD()) { // pre-clear line on OLED @@ -112,10 +111,8 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b { snprintf(buffer2, 256, "%s", entry->filImage.fname); } -#endif int len = strlen(buffer2 + highlightScrollOffset); strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1)); -#if not defined(EXPERIMENTALZERO) if (!screen->IsLCD()) { // space pad the remainder of the line (but not on OLED) @@ -123,56 +120,44 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b buffer1[len++] = ' '; buffer1[columnsMax] = 0; } -#endif if (selected) { if (entry->filImage.fattrib & AM_DIR) { -#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], RGBA(0xff, 0xff, 0xff, 0xff)); -#endif } else { colour = RGBA(0xff, 0, 0, 0xff); if (entry->filImage.fattrib & AM_RDO) colour = palette[VIC2_COLOUR_INDEX_RED]; -#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff)); -#endif } } else { if (entry->filImage.fattrib & AM_DIR) { -#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], BkColour); -#endif } else { colour = palette[VIC2_COLOUR_INDEX_LGREY]; if (entry->filImage.fattrib & AM_RDO) colour = palette[VIC2_COLOUR_INDEX_PINK]; -#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, colour, BkColour); -#endif } } } else // line is blank, write spaces { memset(buffer1, ' ', columnsMax); -#if not defined(EXPERIMENTALZERO) screen->PrintText(false, x, y, buffer1, BkColour, BkColour); -#endif } } void FileBrowser::BrowsableListView::Refresh() { -#if not defined(EXPERIMENTALZERO) u32 index; u32 entryIndex; u32 x = positionX; @@ -197,7 +182,6 @@ void FileBrowser::BrowsableListView::Refresh() } screen->SwapBuffers(); -#endif } void FileBrowser::BrowsableListView::RefreshHighlightScroll() @@ -205,7 +189,6 @@ void FileBrowser::BrowsableListView::RefreshHighlightScroll() char buffer2[256] = { 0 }; FileBrowser::BrowsableList::Entry* entry = list->current; -#if not defined(EXPERIMENTALZERO) if (screen->IsMonocrome()) { if (entry->filImage.fattrib & AM_DIR) @@ -268,7 +251,6 @@ void FileBrowser::BrowsableListView::RefreshHighlightScroll() screen->RefreshRows(rowIndex, 1); } -#endif } bool FileBrowser::BrowsableListView::CheckBrowseNavigation(bool pageOnly) @@ -516,11 +498,14 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM , displayPNGIcons(displayPNGIcons) #if not defined(EXPERIMENTALZERO) , screenMain(screenMain) - , screenLCD(screenLCD) #endif + , screenLCD(screenLCD) , scrollHighlightRate(scrollHighlightRate) , displayingDevices(false) { + + folder.scrollHighlightRate = scrollHighlightRate; + #if not defined(EXPERIMENTALZERO) u32 columns = screenMain->ScaleX(80); u32 rows = (int)(38.0f * screenMain->GetScaleY()); @@ -530,7 +515,6 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM if (rows < 1) rows = 1; - folder.scrollHighlightRate = scrollHighlightRate; folder.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false); positionX = screenMain->ScaleX(1024 - 320); @@ -538,17 +522,17 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM caddySelections.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false); +#endif if (screenLCD) { - columns = screenLCD->Width() / 8; - rows = screenLCD->Height() / screenLCD->GetFontHeight(); - positionX = 0; - positionY = 0; + u32 columns = screenLCD->Width() / 8; + u32 rows = screenLCD->Height() / screenLCD->GetFontHeight(); + u32 positionX = 0; + u32 positionY = 0; folder.AddView(screenLCD, inputMappings, columns, rows, positionX, positionY, true); } -#endif } u32 FileBrowser::Colour(int index) @@ -709,7 +693,6 @@ void FileBrowser::DeviceSwitched() m_IEC_Commands.SetDisplayingDevices(displayingDevices); FolderChanged(); } -#if not defined(EXPERIMENTALZERO) /* void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected) { @@ -788,7 +771,6 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow } } */ -#endif void FileBrowser::RefeshDisplay() { #if not defined(EXPERIMENTALZERO) @@ -800,11 +782,9 @@ void FileBrowser::RefeshDisplay() screenMain->DrawRectangle(0, 0, (int)screenMain->Width(), 17, bgColour); screenMain->PrintText(false, 0, 0, buffer, textColour, bgColour); } -#if not defined(EXPERIMENTALZERO) //u32 offsetX = screenMain->ScaleX(1024 - 320); //RefeshDisplayForBrowsableList(&folder, 0); //RefeshDisplayForBrowsableList(&caddySelections, offsetX, false); -#endif folder.RefreshViews(); caddySelections.RefreshViews(); @@ -816,14 +796,14 @@ void FileBrowser::RefeshDisplay() u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y); screenMain->PrintText(false, 0, y, folder.searchPrefix, textColour, bgColour); } +#else + folder.RefreshViews(); + caddySelections.RefreshViews(); #endif } bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon) { -#if defined(EXPERIMENTALZERO) - return false; -#else bool foundValid = false; filIcon.fname[0] = 0; @@ -845,7 +825,6 @@ bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon) } } return foundValid; -#endif } void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y) @@ -1457,11 +1436,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI char name[17] = { 0 }; unsigned char buffer[260] = { 0 }; int charIndex; -#if defined(EXPERIMENTALZERO) - u32 fontHeight = 16; -#else u32 fontHeight = screenMain->GetFontHeightDirectoryDisplay(); -#endif u32 x = 0; u32 y = 0; char bufferOut[128] = { 0 }; diff --git a/src/FileBrowser.h b/src/FileBrowser.h index bfc9c7f..9a9ec4b 100644 --- a/src/FileBrowser.h +++ b/src/FileBrowser.h @@ -63,9 +63,7 @@ public: BrowsableListView(BrowsableList* list, InputMappings* inputMappings, ScreenBase* screen, u32 columns, u32 rows, u32 positionX, u32 positionY, bool lcdPgUpDown) : list(list) , inputMappings(inputMappings) -#if not defined(EXPERIMENTALZERO) , screen(screen) -#endif , columns(columns) , rows(rows) , positionX(positionX) @@ -86,9 +84,7 @@ public: BrowsableList* list; u32 offset; InputMappings* inputMappings; -#if not defined(EXPERIMENTALZERO) ScreenBase* screen; -#endif u32 columns; u32 rows; u32 positionX; @@ -215,14 +211,10 @@ private: void RefreshFolderEntries(); void UpdateInputFolders(); -#if not defined(EXPERIMENTALZERO) //void UpdateInputDiskCaddy(); -#endif void UpdateCurrentHighlight(); -#if not defined(EXPERIMENTALZERO) //void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true); -#endif bool FillCaddyWithSelections(); bool AddToCaddy(FileBrowser::BrowsableList::Entry* current); @@ -256,8 +248,8 @@ private: BrowsableList caddySelections; #if not defined(EXPERIMENTALZERO) ScreenBase* screenMain; - ScreenBase* screenLCD; #endif + ScreenBase* screenLCD; float scrollHighlightRate; bool displayingDevices; diff --git a/src/InputMappings.h b/src/InputMappings.h index 69977fa..7cdf5c6 100644 --- a/src/InputMappings.h +++ b/src/InputMappings.h @@ -106,17 +106,17 @@ public: #if defined(EXPERIMENTALZERO) inline bool Exit() { - return /*KeyboardFlag(ESC_FLAG) | UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG); + return ButtonFlag(ESC_FLAG); } inline bool NextDisk() { - return /*KeyboardFlag(NEXT_FLAG) | UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG); + return ButtonFlag(NEXT_FLAG); } inline bool PrevDisk() { - return /*KeyboardFlag(PREV_FLAG) | UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG); + return ButtonFlag(PREV_FLAG); } #else inline bool Exit() diff --git a/src/Pi1581.cpp b/src/Pi1581.cpp index ff2b068..930ab5a 100644 --- a/src/Pi1581.cpp +++ b/src/Pi1581.cpp @@ -93,7 +93,7 @@ extern u16 pc; u8 read6502_1581(u16 address) { u8 value = 0; -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) if (address & 0x8000) { value = roms.Read1581(address); @@ -129,7 +129,7 @@ u8 peek6502_1581(u16 address) void write6502_1581(u16 address, const u8 value) { -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) if (address & 0x8000) { return; diff --git a/src/defs.h b/src/defs.h index 7462bdb..1e6f84d 100644 --- a/src/defs.h +++ b/src/defs.h @@ -2,7 +2,9 @@ #define DEFS_H #include "debug.h" - +#ifndef EXPERIMENTALZERO +#define PI1581SUPPORT 1 +#endif // Indicates a Pi with the 40 pin GPIO connector // so that additional functionality (e.g. test pins) can be enabled #if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3) diff --git a/src/main.cpp b/src/main.cpp index 91bc238..33aee90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,7 +101,7 @@ u8 s_u8Memory[0xc000]; int numberOfUSBMassStorageDevices = 0; DiskCaddy diskCaddy; Pi1541 pi1541; -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) Pi1581 pi1581; #endif CEMMCDevice m_EMMC; @@ -250,7 +250,6 @@ void InitialiseHardware() void InitialiseLCD() { -#if not defined(EXPERIMENTALZERO) FILINFO filLcdIcon; int i2cBusMaster = options.I2CBusMaster(); @@ -312,7 +311,6 @@ void InitialiseLCD() screenLCD->RefreshScreen(); } else -#endif { screenLCD = 0; } @@ -612,7 +610,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc DiskImage* diskImage = diskCaddy.SelectFirstImage(); if (diskImage) { -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) if (diskImage->IsD81()) { pi1581.Insert(diskImage); @@ -673,7 +671,7 @@ void GlobalSetDeviceID(u8 id) deviceID = id; m_IEC_Commands.SetDeviceId(id); pi1541.SetDeviceID(id); -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) pi1581.SetDeviceID(id); #endif } @@ -719,6 +717,8 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) if (numberOfImagesMax > 10) numberOfImagesMax = 10; + diskCaddy.Display(); + inputMappings->directDiskSwapRequest = 0; // Force an update on all the buttons now before we start emulation mode. IEC_Bus::ReadBrowseMode(); @@ -1053,8 +1053,9 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } return exitReason; } +#endif - +#if defined(PI1581SUPPORT) EXIT_TYPE Emulate1581(FileBrowser* fileBrowser) { EXIT_TYPE exitReason = EXIT_UNKNOWN; @@ -1251,11 +1252,7 @@ void emulator() roms.lastManualSelectedROMIndex = 0; -#if defined(EXPERIMENTALZERO) - diskCaddy.SetScreen(); -#else diskCaddy.SetScreen(&screen, screenLCD); -#endif fileBrowser = new FileBrowser(inputMappings, &diskCaddy, &roms, &deviceID, options.DisplayPNGIcons(), &screen, screenLCD, options.ScrollHighlightRate()); fileBrowser->DisplayRoot(); pi1541.Initialise(); @@ -1405,7 +1402,7 @@ void emulator() { if (emulating == EMULATING_1541) exitReason = Emulate1541(fileBrowser); -#if not defined(EXPERIMENTALZERO) +#if defined(PI1581SUPPORT) else exitReason = Emulate1581(fileBrowser); #endif @@ -1865,8 +1862,14 @@ void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour, screenLCD->SwapBuffers(); core0RefreshingScreen.Release(); - } +#else + RGBA BkColour = RGBA(0, 0, 0, 0xFF); + + screenLCD->Clear(BkColour); + screenLCD->PrintText(false, x, y, (char*)message, textColour, backgroundColour); + screenLCD->SwapBuffers(); + #endif } @@ -1984,10 +1987,9 @@ extern "C" pi1541.drive.SetVIA(&pi1541.VIA[1]); pi1541.VIA[0].GetPortB()->SetPortOut(0, IEC_Bus::PortB_OnPortOut); IEC_Bus::Initialise(); -#if not defined(EXPERIMENTALZERO) if (screenLCD) screenLCD->ClearInit(0); -#endif + #ifdef HAS_MULTICORE start_core(3, _spin_core); start_core(2, _spin_core);