diff --git a/src/iec_bus.cpp b/src/iec_bus.cpp index 4917cbd..e30dba5 100644 --- a/src/iec_bus.cpp +++ b/src/iec_bus.cpp @@ -67,10 +67,13 @@ u32 IEC_Bus::inputRepeatPrev[5] = { 0 }; u32 IEC_Bus::emulationModeCheckButtonIndex = 0; +unsigned IEC_Bus::gplev0; + + void IEC_Bus::ReadBrowseMode(void) { IOPort* portB = 0; - unsigned gplev0 = read32(ARM_GPIO_GPLEV0); + gplev0 = read32(ARM_GPIO_GPLEV0); int index; for (index = 0; index < buttonCount; ++index) @@ -116,20 +119,20 @@ void IEC_Bus::ReadBrowseMode(void) Resetting = !ignoreReset && ((gplev0 & PIGPIO_MASK_IN_RESET) == (invertIECInputs ? PIGPIO_MASK_IN_RESET : 0)); } -void IEC_Bus::ReadEmulationMode1541(void) +void IEC_Bus::ReadButtonsEmulationMode(void) { - IOPort* portB = 0; - unsigned gplev0 = read32(ARM_GPIO_GPLEV0); - int buttonIndex; for (buttonIndex = 0; buttonIndex < 3; ++buttonIndex) { UpdateButton(buttonIndex, gplev0); } - // Doing it this way screws with the debounce counters. - //UpdateButton(emulationModeCheckButtonIndex, gplev0); - //emulationModeCheckButtonIndex++; - //emulationModeCheckButtonIndex %= buttonCount; +} + +void IEC_Bus::ReadEmulationMode1541(void) +{ + bool AtnaDataSetToOutOld = AtnaDataSetToOut; + IOPort* portB = 0; + gplev0 = read32(ARM_GPIO_GPLEV0); portB = port; @@ -156,10 +159,14 @@ void IEC_Bus::ReadEmulationMode1541(void) if (portB && (portB->GetDirection() & 0x10) == 0) AtnaDataSetToOut = false; // If the ATNA PB4 gets set to an input then we can't be pulling data low. (Maniac Mansion does this) + // moved from PortB_OnPortOut + if (AtnaDataSetToOut) + portB->SetInput(VIAPORTPINS_DATAIN, true); // simulate the read in software + if (!AtnaDataSetToOut && !DataSetToOut) // only sense if we have not brought the line low (because we can't as we have the pin set to output but we can simulate in software) { bool DATAIn = (gplev0 & PIGPIO_MASK_IN_DATA) == (invertIECInputs ? PIGPIO_MASK_IN_DATA : 0); - if (PI_Data != DATAIn) + //if (PI_Data != DATAIn) { PI_Data = DATAIn; portB->SetInput(VIAPORTPINS_DATAIN, DATAIn); // VIA DATAin pb0 output from inverted DIN 5 DATA @@ -174,7 +181,7 @@ void IEC_Bus::ReadEmulationMode1541(void) if (!ClockSetToOut) // only sense if we have not brought the line low (because we can't as we have the pin set to output but we can simulate in software) { bool CLOCKIn = (gplev0 & PIGPIO_MASK_IN_CLOCK) == (invertIECInputs ? PIGPIO_MASK_IN_CLOCK : 0); - if (PI_Clock != CLOCKIn) + //if (PI_Clock != CLOCKIn) { PI_Clock = CLOCKIn; portB->SetInput(VIAPORTPINS_CLOCKIN, CLOCKIn); // VIA CLKin pb2 output from inverted DIN 4 CLK @@ -192,17 +199,9 @@ void IEC_Bus::ReadEmulationMode1541(void) void IEC_Bus::ReadEmulationMode1581(void) { IOPort* portB = 0; - unsigned gplev0 = read32(ARM_GPIO_GPLEV0); + gplev0 = read32(ARM_GPIO_GPLEV0); - int buttonIndex; - for (buttonIndex = 0; buttonIndex < 3; ++buttonIndex) - { - UpdateButton(buttonIndex, gplev0); - } - // Doing it this way screws with the debounce counters. - //UpdateButton(emulationModeCheckButtonIndex, gplev0); - //emulationModeCheckButtonIndex++; - //emulationModeCheckButtonIndex %= buttonCount; + ReadButtonsEmulationMode(); portB = port; @@ -275,3 +274,99 @@ void IEC_Bus::ReadEmulationMode1581(void) Resetting = !ignoreReset && ((gplev0 & PIGPIO_MASK_IN_RESET) == (invertIECInputs ? PIGPIO_MASK_IN_RESET : 0)); } +void IEC_Bus::RefreshOuts1541(void) +{ + unsigned set = 0; + unsigned clear = 0; + unsigned tmp; + + if (!splitIECLines) + { + unsigned outputs = 0; + + if (AtnaDataSetToOut || DataSetToOut) outputs |= (FS_OUTPUT << ((PIGPIO_DATA - 10) * 3)); + if (ClockSetToOut) outputs |= (FS_OUTPUT << ((PIGPIO_CLOCK - 10) * 3)); + + unsigned nValue = (myOutsGPFSEL1 & PI_OUTPUT_MASK_GPFSEL1) | outputs; + write32(ARM_GPIO_GPFSEL1, nValue); + } + else + { + if (AtnaDataSetToOut || DataSetToOut) set |= 1 << PIGPIO_OUT_DATA; + else clear |= 1 << PIGPIO_OUT_DATA; + + if (ClockSetToOut) set |= 1 << PIGPIO_OUT_CLOCK; + else clear |= 1 << PIGPIO_OUT_CLOCK; + + if (!invertIECOutputs) { + tmp = set; + set = clear; + clear = tmp; + } + } + + if (OutputLED) set |= 1 << PIGPIO_OUT_LED; + else clear |= 1 << PIGPIO_OUT_LED; + + if (OutputSound) set |= 1 << PIGPIO_OUT_SOUND; + else clear |= 1 << PIGPIO_OUT_SOUND; + + write32(ARM_GPIO_GPCLR0, clear); + write32(ARM_GPIO_GPSET0, set); +} + +void IEC_Bus::PortB_OnPortOut(void* pUserData, unsigned char status) +{ + bool oldDataSetToOut = DataSetToOut; + bool oldClockSetToOut = ClockSetToOut; + bool AtnaDataSetToOutOld = AtnaDataSetToOut; + + // These are the values the VIA is trying to set the outputs to + VIA_Atna = (status & (unsigned char)VIAPORTPINS_ATNAOUT) != 0; + VIA_Data = (status & (unsigned char)VIAPORTPINS_DATAOUT) != 0; // VIA DATAout PB1 inverted and then connected to DIN DATA + VIA_Clock = (status & (unsigned char)VIAPORTPINS_CLOCKOUT) != 0; // VIA CLKout PB3 inverted and then connected to DIN CLK + + if (VIA) + { + // Emulate the XOR gate UD3 + AtnaDataSetToOut = (VIA_Atna != PI_Atn); + } + else + { + AtnaDataSetToOut = (VIA_Atna & PI_Atn); + } + + //if (AtnaDataSetToOut) + //{ + // // if the output of the XOR gate is high (ie VIA_Atna != PI_Atn) then this is inverted and pulls DATA low (activating it) + // //PI_Data = true; + // if (port) port->SetInput(VIAPORTPINS_DATAIN, true); // simulate the read in software + //} + + if (VIA && port) + { + // If the VIA's data and clock outputs ever get set to inputs the real hardware reads these lines as asserted. + bool PB1SetToInput = (port->GetDirection() & 2) == 0; + bool PB3SetToInput = (port->GetDirection() & 8) == 0; + if (PB1SetToInput) VIA_Data = true; + if (PB3SetToInput) VIA_Clock = true; + } + + ClockSetToOut = VIA_Clock; + DataSetToOut = VIA_Data; + + //if (!oldDataSetToOut && DataSetToOut) + //{ + // //PI_Data = true; + // if (port) port->SetInput(VIAPORTPINS_DATAOUT, true); // simulate the read in software + //} + + //if (!oldClockSetToOut && ClockSetToOut) + //{ + // //PI_Clock = true; + // if (port) port->SetInput(VIAPORTPINS_CLOCKIN, true); // simulate the read in software + //} + + //if (AtnaDataSetToOutOld ^ AtnaDataSetToOut) + // RefreshOuts1541(); +} diff --git a/src/iec_bus.h b/src/iec_bus.h index 87fa7ff..8d944c5 100644 --- a/src/iec_bus.h +++ b/src/iec_bus.h @@ -351,6 +351,7 @@ public: static void ReadBrowseMode(void); static void ReadEmulationMode1541(void); + static void ReadButtonsEmulationMode(void); static void ReadEmulationMode1581(void); static void WaitUntilReset(void) @@ -369,99 +370,9 @@ public: } // Out going - static void PortB_OnPortOut(void* pUserData, unsigned char status) - { - bool oldDataSetToOut = DataSetToOut; - bool oldClockSetToOut = ClockSetToOut; + static void PortB_OnPortOut(void* pUserData, unsigned char status); - // These are the values the VIA is trying to set the outputs to - VIA_Atna = (status & (unsigned char)VIAPORTPINS_ATNAOUT) != 0; - VIA_Data = (status & (unsigned char)VIAPORTPINS_DATAOUT) != 0; // VIA DATAout PB1 inverted and then connected to DIN DATA - VIA_Clock = (status & (unsigned char)VIAPORTPINS_CLOCKOUT) != 0; // VIA CLKout PB3 inverted and then connected to DIN CLK - - if (VIA) - { - // Emulate the XOR gate UD3 - AtnaDataSetToOut = (VIA_Atna != PI_Atn); - } - else - { - AtnaDataSetToOut = (VIA_Atna & PI_Atn); - } - - if (AtnaDataSetToOut) - { - // if the output of the XOR gate is high (ie VIA_Atna != PI_Atn) then this is inverted and pulls DATA low (activating it) - PI_Data = true; - if (port) port->SetInput(VIAPORTPINS_DATAIN, true); // simulate the read in software - } - - if (VIA && port) - { - // If the VIA's data and clock outputs ever get set to inputs the real hardware reads these lines as asserted. - bool PB1SetToInput = (port->GetDirection() & 2) == 0; - bool PB3SetToInput = (port->GetDirection() & 8) == 0; - if (PB1SetToInput) VIA_Data = true; - if (PB3SetToInput) VIA_Clock = true; - } - - ClockSetToOut = VIA_Clock; - DataSetToOut = VIA_Data; - - if (!oldDataSetToOut && DataSetToOut) - { - PI_Data = true; - if (port) port->SetInput(VIAPORTPINS_DATAOUT, true); // simulate the read in software - } - - if (!oldClockSetToOut && ClockSetToOut) - { - PI_Clock = true; - if (port) port->SetInput(VIAPORTPINS_CLOCKIN, true); // simulate the read in software - } - - } - - static inline void RefreshOuts1541(void) - { - unsigned set = 0; - unsigned clear = 0; - unsigned tmp; - - if (!splitIECLines) - { - unsigned outputs = 0; - - if (AtnaDataSetToOut || DataSetToOut) outputs |= (FS_OUTPUT << ((PIGPIO_DATA - 10) * 3)); - if (ClockSetToOut) outputs |= (FS_OUTPUT << ((PIGPIO_CLOCK - 10) * 3)); - - unsigned nValue = (myOutsGPFSEL1 & PI_OUTPUT_MASK_GPFSEL1) | outputs; - write32(ARM_GPIO_GPFSEL1, nValue); - } - else - { - if (AtnaDataSetToOut || DataSetToOut) set |= 1 << PIGPIO_OUT_DATA; - else clear |= 1 << PIGPIO_OUT_DATA; - - if (ClockSetToOut) set |= 1 << PIGPIO_OUT_CLOCK; - else clear |= 1 << PIGPIO_OUT_CLOCK; - - if (!invertIECOutputs) { - tmp = set; - set = clear; - clear = tmp; - } - } - - if (OutputLED) set |= 1 << PIGPIO_OUT_LED; - else clear |= 1 << PIGPIO_OUT_LED; - - if (OutputSound) set |= 1 << PIGPIO_OUT_SOUND; - else clear |= 1 << PIGPIO_OUT_SOUND; - - write32(ARM_GPIO_GPSET0, set); - write32(ARM_GPIO_GPCLR0, clear); - } + static void RefreshOuts1541(void); static inline void RefreshOuts1581(void) { @@ -697,6 +608,8 @@ private: static u32 emulationModeCheckButtonIndex; + static unsigned gplev0; + static bool PI_Atn; static bool PI_Data; static bool PI_Clock; diff --git a/src/main.cpp b/src/main.cpp index 8c0b636..858aaa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -724,7 +724,8 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) //read32(ARM_SYSTIMER_CLO); //Each one of these is > 100ns //read32(ARM_SYSTIMER_CLO); //read32(ARM_SYSTIMER_CLO); - //IEC_Bus::RefreshOuts(); // Now output all outputs. + + IEC_Bus::RefreshOuts1541(); // Now output all outputs. IEC_Bus::OutputLED = pi1541.drive.IsLEDOn(); if (IEC_Bus::OutputLED ^ oldLED) @@ -749,21 +750,11 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser) } } - //if (options.SoundOnGPIO() && headSoundCounter > 0) - //{ - // headSoundFreqCounter--; // Continue updating a GPIO non DMA sound. - // if (headSoundFreqCounter <= 0) - // { - // headSoundFreqCounter = headSoundFreq; - // headSoundCounter -= headSoundFreq * 8; - // IEC_Bus::OutputSound = !IEC_Bus::OutputSound; - // } - //} - - IEC_Bus::RefreshOuts1541(); // Now output all outputs. } + IEC_Bus::ReadButtonsEmulationMode(); + // Other core will check the uart (as it is slow) (could enable uart irqs - will they execute on this core?) inputMappings->CheckKeyboardEmulationMode(numberOfImages, numberOfImagesMax); inputMappings->CheckButtonsEmulationMode();