pi1541/src/iec_bus.cpp

185 lines
5.6 KiB
C++
Raw Normal View History

2018-05-20 04:53:34 +00:00
// Pi1541 - A Commodore 1541 disk drive emulator
// Copyright(C) 2018 Stephen White
//
// This file is part of Pi1541.
//
// Pi1541 is free software : you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pi1541 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
#include "iec_bus.h"
static int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned);
2018-05-20 04:53:34 +00:00
u32 IEC_Bus::PIGPIO_MASK_IN_ATN = 1 << PIGPIO_ATN;
u32 IEC_Bus::PIGPIO_MASK_IN_DATA = 1 << PIGPIO_DATA;
u32 IEC_Bus::PIGPIO_MASK_IN_CLOCK = 1 << PIGPIO_CLOCK;
u32 IEC_Bus::PIGPIO_MASK_IN_SRQ = 1 << PIGPIO_SRQ;
u32 IEC_Bus::PIGPIO_MASK_IN_RESET = 1 << PIGPIO_RESET;
bool IEC_Bus::PI_Atn = false;
bool IEC_Bus::PI_Data = false;
bool IEC_Bus::PI_Clock = false;
bool IEC_Bus::PI_Reset = false;
bool IEC_Bus::VIA_Atna = false;
bool IEC_Bus::VIA_Data = false;
bool IEC_Bus::VIA_Clock = false;
bool IEC_Bus::DataSetToOut = false;
bool IEC_Bus::AtnaDataSetToOut = false;
bool IEC_Bus::ClockSetToOut = false;
bool IEC_Bus::OutputLED = false;
bool IEC_Bus::OutputSound = false;
bool IEC_Bus::Resetting = false;
bool IEC_Bus::splitIECLines = false;
bool IEC_Bus::invertIECInputs = false;
bool IEC_Bus::invertIECOutputs = true;
bool IEC_Bus::ignoreReset = false;
2018-05-20 04:53:34 +00:00
u32 IEC_Bus::myOutsGPFSEL1 = 0;
u32 IEC_Bus::myOutsGPFSEL0 = 0;
bool IEC_Bus::InputButton[5] = { 0 };
bool IEC_Bus::InputButtonPrev[5] = { 0 };
u32 IEC_Bus::validInputCount[5] = { 0 };
2018-05-20 04:53:34 +00:00
u32 IEC_Bus::inputRepeatThreshold[5];
u32 IEC_Bus::inputRepeat[5] = { 0 };
u32 IEC_Bus::inputRepeatPrev[5] = { 0 };
2018-05-20 04:53:34 +00:00
m6522* IEC_Bus::VIA = 0;
u32 IEC_Bus::emulationModeCheckButtonIndex = 0;
void IEC_Bus::ReadBrowseMode(void)
2018-05-20 04:53:34 +00:00
{
IOPort* portB = 0;
unsigned gplev0 = read32(ARM_GPIO_GPLEV0);
int index;
for (index = 0; index < buttonCount; ++index)
{
UpdateButton(index, gplev0);
}
bool ATNIn = (gplev0 & PIGPIO_MASK_IN_ATN) == (invertIECInputs ? PIGPIO_MASK_IN_ATN : 0);
if (PI_Atn != ATNIn)
{
PI_Atn = ATNIn;
}
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)
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)
{
PI_Data = DATAIn;
}
}
else
{
PI_Data = true;
}
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)
{
PI_Clock = CLOCKIn;
}
}
else
{
PI_Clock = true;
}
Resetting = !ignoreReset && ((gplev0 & PIGPIO_MASK_IN_RESET) == (invertIECInputs ? PIGPIO_MASK_IN_RESET : 0));
}
void IEC_Bus::ReadEmulationMode(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;
portB = VIA->GetPortB();
2018-05-20 04:53:34 +00:00
bool ATNIn = (gplev0 & PIGPIO_MASK_IN_ATN) == (invertIECInputs ? PIGPIO_MASK_IN_ATN : 0);
if (PI_Atn != ATNIn)
{
PI_Atn = ATNIn;
//if (VIA)
2018-05-20 04:53:34 +00:00
{
if ((portB->GetDirection() & 0x10) != 0)
{
// Emulate the XOR gate UD3
// We only need to do this when fully emulating, iec commands do this internally
AtnaDataSetToOut = (VIA_Atna != PI_Atn);
}
portB->SetInput(VIAPORTPINS_ATNIN, ATNIn); //is inverted and then connected to pb7 and ca1
VIA->InputCA1(ATNIn);
}
}
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)
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)
{
PI_Data = DATAIn;
portB->SetInput(VIAPORTPINS_DATAIN, DATAIn); // VIA DATAin pb0 output from inverted DIN 5 DATA
2018-05-20 04:53:34 +00:00
}
}
else
{
PI_Data = true;
portB->SetInput(VIAPORTPINS_DATAIN, true); // simulate the read in software
2018-05-20 04:53:34 +00:00
}
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);
2018-05-20 04:53:34 +00:00
if (PI_Clock != CLOCKIn)
{
PI_Clock = CLOCKIn;
portB->SetInput(VIAPORTPINS_CLOCKIN, CLOCKIn); // VIA CLKin pb2 output from inverted DIN 4 CLK
2018-05-20 04:53:34 +00:00
}
}
else
{
PI_Clock = true;
portB->SetInput(VIAPORTPINS_CLOCKIN, true); // simulate the read in software
2018-05-20 04:53:34 +00:00
}
Resetting = !ignoreReset && ((gplev0 & PIGPIO_MASK_IN_RESET) == (invertIECInputs ? PIGPIO_MASK_IN_RESET : 0));
2018-05-20 04:53:34 +00:00
}