diff --git a/EightBit.sln b/EightBit.sln
index 5b626bb..107f639 100644
--- a/EightBit.sln
+++ b/EightBit.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809", "MC6809\MC6809.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809.UnitTest", "MC6809\MC6809.UnitTest\MC6809.UnitTest.csproj", "{4391A363-ECEF-44C8-9335-BF6ECB811E4B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6850", "MC6850\MC6850.csproj", "{A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -153,6 +155,18 @@ Global
{4391A363-ECEF-44C8-9335-BF6ECB811E4B}.Release|x64.Build.0 = Release|Any CPU
{4391A363-ECEF-44C8-9335-BF6ECB811E4B}.Release|x86.ActiveCfg = Release|Any CPU
{4391A363-ECEF-44C8-9335-BF6ECB811E4B}.Release|x86.Build.0 = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|x64.Build.0 = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Debug|x86.Build.0 = Debug|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x64.ActiveCfg = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x64.Build.0 = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x86.ActiveCfg = Release|Any CPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MC6809/MC6809.cs b/MC6809/MC6809.cs
index 86176ce..5116696 100644
--- a/MC6809/MC6809.cs
+++ b/MC6809/MC6809.cs
@@ -106,7 +106,7 @@
public ref byte CC => ref this.cc;
- public bool Halted => this.HALT().Lowered();
+ public bool Halted => this.HALT.Lowered();
public int EntireRegisterSet => this.CC & (byte)StatusBits.EF;
@@ -136,15 +136,15 @@
private bool GT => !this.LE; // !(Z OR (N XOR V))
- public ref PinLevel NMI() => ref this.nmiLine;
+ public ref PinLevel NMI => ref this.nmiLine;
- public ref PinLevel FIRQ() => ref this.firqLine;
+ public ref PinLevel FIRQ => ref this.firqLine;
- public ref PinLevel HALT() => ref this.haltLine;
+ public ref PinLevel HALT => ref this.haltLine;
- public ref PinLevel BA() => ref this.baLine;
+ public ref PinLevel BA => ref this.baLine;
- public ref PinLevel BS() => ref this.bsLine;
+ public ref PinLevel BS => ref this.bsLine;
public void Halt()
{
@@ -173,11 +173,11 @@
{
this.HandleRESET();
}
- else if (this.NMI().Lowered())
+ else if (this.NMI.Lowered())
{
this.HandleNMI();
}
- else if (this.FIRQ().Lowered() && (this.FastInterruptMasked == 0))
+ else if (this.FIRQ.Lowered() && (this.FastInterruptMasked == 0))
{
this.HandleFIRQ();
}
@@ -230,70 +230,70 @@
public void RaiseNMI()
{
this.OnRaisingNMI();
- this.NMI().Raise();
+ this.NMI.Raise();
this.OnRaisedNMI();
}
public void LowerNMI()
{
this.OnLoweringNMI();
- this.NMI().Lower();
+ this.NMI.Lower();
this.OnLoweredNMI();
}
public void RaiseFIRQ()
{
this.OnRaisingFIRQ();
- this.FIRQ().Raise();
+ this.FIRQ.Raise();
this.OnRaisedFIRQ();
}
public void LowerFIRQ()
{
this.OnLoweringFIRQ();
- this.FIRQ().Lower();
+ this.FIRQ.Lower();
this.OnLoweredFIRQ();
}
public void RaiseHALT()
{
this.OnRaisingHALT();
- this.HALT().Raise();
+ this.HALT.Raise();
this.OnRaisedHALT();
}
public void LowerHALT()
{
this.OnLoweringHALT();
- this.HALT().Lower();
+ this.HALT.Lower();
this.OnLoweredHALT();
}
public void RaiseBA()
{
this.OnRaisingBA();
- this.BA().Raise();
+ this.BA.Raise();
this.OnRaisedBA();
}
public void LowerBA()
{
this.OnLoweringBA();
- this.BA().Lower();
+ this.BA.Lower();
this.OnLoweredBA();
}
public void RaiseBS()
{
this.OnRaisingBS();
- this.BS().Raise();
+ this.BS.Raise();
this.OnRaisedBS();
}
public void LowerBS()
{
this.OnLoweringBS();
- this.BS().Lower();
+ this.BS.Lower();
this.OnLoweredBS();
}
diff --git a/MC6850/MC6850.cs b/MC6850/MC6850.cs
new file mode 100644
index 0000000..9fc6688
--- /dev/null
+++ b/MC6850/MC6850.cs
@@ -0,0 +1,506 @@
+//
+// Copyright (c) Adrian Conlon. All rights reserved.
+//
+
+namespace EightBit
+{
+ using System;
+
+ // +--------+----------------------------------------------------------------------------------+
+ // | | Buffer address |
+ // | +------------------+------------------+--------------------+-----------------------+
+ // | | _ | _ | _ | _ |
+ // | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W |
+ // | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
+ // | Line | Transmit | Receive | | |
+ // | Number | Data | Data | Control | Status |
+ // | | Register | Register | register | register |
+ // | +------------------+------------------+--------------------+-----------------------+
+ // | | (Write only) + (Read only) + (Write only) | (Read only) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
+ // | | | | select 1 (CR0) | full (RDRF) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register|
+ // | | | | select 2 (CR1) | empty (TDRE) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect |
+ // | | | | (CR2) | (DCD active) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send |
+ // | | | | (CR3) | (CTS active) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error |
+ // | | | | (CR4) | (FE) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun |
+ // | | | | (CR5) | (OVRN) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) |
+ // | | | | (CR6) | |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request |
+ // | | | | enable (CR7) | (IRQ active) |
+ // +--------+------------------+------------------+--------------------+-----------------------+
+ // * Leading bit = LSB = Bit 0
+ // ** Data bit will be zero in 7-bit plus parity modes
+ // *** Data bit is "don't care" in 7-bit plus parity modes
+
+ public sealed class MC6850 : ClockedChip
+ {
+ private PinLevel rxdataLine = PinLevel.Low;
+ private PinLevel txdataLine = PinLevel.Low;
+
+ private PinLevel rtsLine = PinLevel.Low;
+ private PinLevel ctsLine = PinLevel.Low;
+ private PinLevel dcdLine = PinLevel.Low;
+ private PinLevel oldDcdLine = PinLevel.Low; // So we can detect low -> high transition
+
+ private PinLevel rxClkLine = PinLevel.Low;
+ private PinLevel txClkLine = PinLevel.Low;
+
+ private PinLevel cs0Line = PinLevel.Low;
+ private PinLevel cs1Line = PinLevel.Low;
+ private PinLevel cs2Line = PinLevel.Low;
+
+ private PinLevel rsLine = PinLevel.Low;
+ private PinLevel rwLine = PinLevel.Low;
+
+ private PinLevel eLine = PinLevel.Low;
+ private PinLevel irqLine = PinLevel.Low;
+
+ private byte data = 0;
+
+ private bool statusRead = false;
+
+ // Control registers
+ private CounterDivideSelect counterDivide = CounterDivideSelect.One;
+ private WordSelect wordSelect = WordSelect.SevenEvenTwo;
+ private TransmitterControl transmitControl = TransmitterControl.ReadyLowInterruptDisabled;
+ private ReceiveControl receiveControl = ReceiveControl.ReceiveInterruptDisable;
+
+ // Status registers
+ private bool statusRDRF = false;
+ private bool statusTDRE = true;
+ private bool statusOVRN = false;
+
+ // Data registers
+ private byte tdr = 0;
+ private byte rdr = 0;
+
+ private StartupCondition startup = StartupCondition.WarmStart;
+
+ public event EventHandler Accessing;
+
+ public event EventHandler Accessed;
+
+ public event EventHandler Transmitting;
+
+ public event EventHandler Transmitted;
+
+ public event EventHandler Receiving;
+
+ public event EventHandler Received;
+
+ public enum ControlRegisters
+ {
+ CR0 = 0b1, // Counter divide
+ CR1 = 0b10, // "
+ CR2 = 0b100, // Word select
+ CR3 = 0b1000, // "
+ CR4 = 0b10000, // "
+ CR5 = 0b100000, // Transmit control
+ CR6 = 0b1000000, // "
+ CR7 = 0b10000000, // Receive control
+ }
+
+ // CR0 and CR1
+ public enum CounterDivideSelect
+ {
+ One = 0b00,
+ Sixteen = 0b01,
+ SixtyFour = 0b10,
+ MasterReset = 0b11,
+ }
+
+ // CR2, CR3 and CR4
+ public enum WordSelect
+ {
+ SevenEvenTwo = 0b000,
+ SevenOddTwo = 0b001,
+ SevenEvenOne = 0b010,
+ SevenOddOne = 0b011,
+ EightTwo = 0b100,
+ EightOne = 0b101,
+ EightEvenOne = 0b110,
+ EightOddOne = 0b111,
+ }
+
+ // CR5 and CR6
+ public enum TransmitterControl
+ {
+ ReadyLowInterruptDisabled = 0b00,
+ ReadyLowInterruptEnabled = 0b01,
+ ReadyHighInterruptDisabled = 0b10,
+ ReadyLowInterruptDisabledTransmitBreak = 0b11,
+ }
+
+ // CR7
+ public enum ReceiveControl
+ {
+ ReceiveInterruptDisable = 0b0,
+ ReceiveInterruptEnable = 0b1, // Triggers on: RDR full, overrun, DCD low -> high
+ }
+
+ // STATUS REGISTER Information on the status of the ACIA is
+ // available to the MPU by reading the ACIA Status Register.
+ // This read-only register is selected when RS is low and R/W is high.
+ // Information stored in this register indicates the status of the
+ // Transmit Data Register, the Receive Data Register and error logic,
+ // and the peripheral/modem status inputs of the ACIA
+ public enum StatusRegisters
+ {
+ // Receive Data Register Full (RDRF), Bit 0 - Receive Data
+ // Register Full indicates that received data has been
+ // transferred to the Receive Data Register. RDRF is cleared
+ // after an MPU read of the Receive Data Register or by a
+ // master reset. The cleared or empty state indicates that the
+ // contents of the Receive Data Register are not current.
+ // Data Carrier Detect being high also causes RDRF to indicate
+ // empty.
+ STATUS_RDRF = 0b1,
+
+ // Transmit Data Register Empty (TDRE), Bit 1 - The Transmit
+ // Data Register Empty bit being set high indicates that the
+ // Transmit Data Register contents have been transferred and
+ // that new data may be entered. The low state indicates that
+ // the register is full and that transmission of a new
+ // character has not begun since the last write data command.
+ STATUS_TDRE = 0b10,
+
+ // ___
+ // Data Carrier Detect (DCD), Bit 2 - The Data Carrier Detect
+ // bit will be high when the DCD (low) input from a modem has gone
+ // high to indicate that a carrier is not present. This bit
+ // going high causes an Interrupt Request to be generated when
+ // the Receive Interrupt Enable is set. It remains high after
+ // the DCD (low) input is returned low until cleared by first reading
+ // the Status Register and then the Data Register or until a
+ // master reset occurs. If the DCD (low) input remains high after
+ // read status and read data or master reset has occurred, the
+ // interrupt is cleared, the DCD (low) status bit remains high and
+ // will follow the DCD (low) input.
+ STATUS_DCD = 0b100,
+
+ // ___
+ // Clear-to-Send (CTS), Bit 3 - The Clear-to-Send bit indicates
+ // the state of the Clear-to-Send input from a modem. A low CTS (low)
+ // indicates that there is a Clear-to-Send from the modem. In
+ // the high state, the Transmit Data Register Empty bit is
+ // inhibited and the Clear-to-Send status bit will be high.
+ // Master reset does not affect the Clear-to-Send status bit.
+ STATUS_CTS = 0b1000,
+
+ // Framing Error (FE), Bit 4 - Framing error indicates that the
+ // received character is improperly framed by a start and a
+ // stop bit and is detected by the absence of the first stop
+ // bit. This error indicates a synchronization error, faulty
+ // transmission, or a break condition. The framing error flag
+ // is set or reset during the receive data transfer time.
+ // Therefore, this error indicator is present throughout the
+ // time that the associated character is available.
+ STATUS_FE = 0b10000,
+
+ // Receiver Overrun (OVRN), Bit 5- Overrun is an error flag
+ // that indicates that one or more characters in the data
+ // stream were lost. That is, a character or a number of
+ // characters were received but not read from the Receive
+ // Data Register (RDR) prior to subsequent characters being
+ // received. The overrun condition begins at the midpoint of
+ // the last bit of the second character received in succession
+ // without a read of the RDR having occurred. The Overrun does
+ // not occur in the Status Register until the valid character
+ // prior to Overrun has been read. The RDRF bit remains set
+ // until the Overrun is reset. Character synchronization is
+ // maintained during the Overrun condition. The Overrun
+ // indication is reset after the reading of data from the
+ // Receive Data Register or by a Master Reset.
+ STATUS_OVRN = 0b100000,
+
+ // Parity Error (PE), Bit 6 - The parity error flag indicates
+ // that the number of highs {ones) in the character does not
+ // agree with the preselected odd or even parity. Odd parity
+ // is defined to be when the total number of ones is odd. The
+ // parity error indication will be present as long as the data
+ // character is in the RDR. If no parity is selected, then both
+ // the transmitter parity generator output and the receiver
+ // parity check results are inhibited
+ STATUS_PE = 0b1000000,
+
+ // ___
+ // Interrupt Request (IRQ), Bit 7- The IRQ (low) bit indicates the
+ // state of the IRQ (low) output. Any interrupt condition with its
+ // applicable enable will be indicated in this status bit.
+ // Anytime the IRQ (low) output is low the IRQ bit will be high to
+ // indicate the interrupt or service request status. IRQ (low) is
+ // cleared by a read operation to the Receive Data Register or
+ // a write operation to the Transmit Data Register.
+ STATUS_IRQ = 0b10000000,
+ }
+
+ private enum StartupCondition
+ {
+ ColdStart,
+ WarmStart,
+ Unknown,
+ }
+
+ // Receive data, (I) Active high
+ public ref PinLevel RXDATA => ref this.rxdataLine;
+
+ // Transmit data, (O) Active high
+ public ref PinLevel TXDATA => ref this.txdataLine;
+
+ // Request to send, (O) Active low
+ public ref PinLevel RTS => ref this.rtsLine;
+
+ // Clear to send, (I) Active low
+ public ref PinLevel CTS => ref this.ctsLine;
+
+ // Data carrier detect, (I) Active low
+ public ref PinLevel DCD => ref this.dcdLine;
+
+ // Transmit clock, (I) Active high
+ public ref PinLevel RXCLK => ref this.rxClkLine;
+
+ // Receive clock, (I) Active high
+ public ref PinLevel TXCLK => ref this.txClkLine;
+
+ // Chip select, bit 0, (I) Active high
+ public ref PinLevel CS0 => ref this.cs0Line;
+
+ // Chip select, bit 1, (I) Active high
+ public ref PinLevel CS1 => ref this.cs1Line;
+
+ // Chip select, bit 2, (I) Active low
+ public ref PinLevel CS2 => ref this.cs2Line;
+
+ // Register select, (I) Active high
+ public ref PinLevel RS => ref this.rsLine;
+
+ // Read/Write, (I) Read high, write low
+ public ref PinLevel RW => ref this.rwLine;
+
+ // ACIA Enable, (I) Active high
+ public ref PinLevel E => ref this.eLine;
+
+ // Interrupt request, (O) Active low
+ public ref PinLevel IRQ => ref this.irqLine;
+
+ // Data, (I/O)
+ public ref byte DATA => ref this.data;
+
+ // Expose these internal registers, so we can update internal state
+
+ // Transmit data register;
+ public ref byte TDR => ref this.tdr;
+
+ // Receive data register;
+ public ref byte RDR => ref this.rdr;
+
+ public bool Activated => this.Powered && this.E.Raised() && this.Selected;
+
+ public bool Selected => this.CS0.Raised() && this.CS1.Raised() && this.CS2.Lowered();
+
+ private bool TransmitInterruptEnabled => this.transmitControl == TransmitterControl.ReadyLowInterruptEnabled;
+
+ private bool ReceiveInterruptEnabled => this.receiveControl == ReceiveControl.ReceiveInterruptEnable;
+
+ private bool TransmitReadyHigh => this.transmitControl == TransmitterControl.ReadyHighInterruptDisabled;
+
+ private bool TransmitReadyLow => !this.TransmitReadyHigh;
+
+ private byte Status
+ {
+ get
+ {
+ byte status = 0;
+ SetFlag(status, StatusRegisters.STATUS_RDRF, this.statusRDRF);
+ SetFlag(status, StatusRegisters.STATUS_TDRE, this.statusTDRE);
+ SetFlag(status, StatusRegisters.STATUS_DCD, this.DCD.Lowered());
+ SetFlag(status, StatusRegisters.STATUS_CTS, this.CTS.Raised());
+ ClearFlag(status, StatusRegisters.STATUS_FE);
+ SetFlag(status, StatusRegisters.STATUS_OVRN, this.statusOVRN);
+ ClearFlag(status, StatusRegisters.STATUS_PE);
+ SetFlag(status, StatusRegisters.STATUS_IRQ, this.IRQ.Lowered());
+ return status;
+ }
+ }
+
+ public override void RaisePOWER()
+ {
+ base.RaisePOWER();
+ this.startup = StartupCondition.ColdStart;
+ }
+
+ public void Step()
+ {
+ this.ResetCycles();
+
+ this.OnAccessing();
+
+ this.Tick();
+
+ var writing = this.RW.Lowered();
+ var reading = !writing;
+
+ var registers = this.RS.Lowered();
+ var transferring = !registers;
+
+ if (registers)
+ {
+ if (writing)
+ {
+ this.counterDivide = (CounterDivideSelect)(this.DATA & (byte)(ControlRegisters.CR0 | ControlRegisters.CR1));
+ if (this.counterDivide == CounterDivideSelect.MasterReset)
+ {
+ this.Reset();
+ }
+ else
+ {
+ this.wordSelect = (WordSelect)((this.DATA & (byte)(ControlRegisters.CR2 | ControlRegisters.CR3 | ControlRegisters.CR4)) >> 2);
+ this.transmitControl = (TransmitterControl)((this.DATA & (byte)(ControlRegisters.CR5 | ControlRegisters.CR6)) >> 5);
+ this.receiveControl = (ReceiveControl)((this.DATA & (byte)ControlRegisters.CR7) >> 7);
+ if (this.TransmitReadyHigh)
+ {
+ this.RTS.Raise();
+ }
+ else
+ {
+ this.RTS.Lower();
+ }
+ }
+ }
+ else
+ {
+ this.DATA = this.Status;
+ }
+ }
+ else
+ {
+ this.IRQ.Raise();
+ if (writing)
+ {
+ this.StartTransmit();
+ }
+ else
+ {
+ this.CompleteReceive();
+ }
+ }
+
+ // Catch the transition to lost carrier
+ if (this.oldDcdLine.Lowered() && this.DCD.Raised())
+ {
+ this.IRQ.Raise();
+ this.statusRead = false;
+ }
+
+ this.oldDcdLine = this.dcdLine;
+
+ this.OnAccessed();
+ }
+
+ public void MarkTransmitComplete()
+ {
+ this.statusTDRE = this.CTS.Lowered();
+ if (this.statusTDRE && this.TransmitInterruptEnabled)
+ {
+ this.IRQ.Lower();
+ }
+
+ this.OnTransmitted();
+ }
+
+ public void MarkReceiveStarting()
+ {
+ this.statusOVRN = this.statusRDRF; // If the RDR was already full, this means we're losing data
+ this.statusRDRF = true;
+ if (this.ReceiveInterruptEnabled)
+ {
+ this.IRQ.Lower();
+ }
+
+ this.OnReceiving();
+ }
+
+ public string DumpStatus()
+ {
+ var value = this.Status;
+ var returned = string.Empty;
+ returned += "(";
+ returned += (value & (byte)StatusRegisters.STATUS_IRQ) != 0 ? "IRQ" : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_PE) != 0 ? "PE " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_OVRN) != 0 ? "OVRN " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_FE) != 0 ? "FE " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_CTS) != 0 ? "CTS " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_DCD) != 0 ? "DCD " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_TDRE) != 0 ? "TDRE " : "- ";
+ returned += (value & (byte)StatusRegisters.STATUS_RDRF) != 0 ? "RDRF " : "- ";
+ returned += ") ";
+ return returned;
+ }
+
+ private static byte SetFlag(byte f, StatusRegisters flag) => SetFlag(f, (byte)flag);
+
+ private static byte SetFlag(byte f, StatusRegisters flag, int condition) => SetFlag(f, (byte)flag, condition);
+
+ private static byte SetFlag(byte f, StatusRegisters flag, bool condition) => SetFlag(f, (byte)flag, condition);
+
+ private static byte ClearFlag(byte f, StatusRegisters flag) => ClearFlag(f, (byte)flag);
+
+ private static byte ClearFlag(byte f, StatusRegisters flag, int condition) => ClearFlag(f, (byte)flag, condition);
+
+ private void OnAccessing() => this.Accessing?.Invoke(this, EventArgs.Empty);
+
+ private void OnAccessed() => this.Accessed?.Invoke(this, EventArgs.Empty);
+
+ private void OnTransmitting() => this.Transmitting?.Invoke(this, EventArgs.Empty);
+
+ private void OnTransmitted() => this.Transmitted?.Invoke(this, EventArgs.Empty);
+
+ private void OnReceiving() => this.Receiving?.Invoke(this, EventArgs.Empty);
+
+ private void OnReceived() => this.Received?.Invoke(this, EventArgs.Empty);
+
+ private void Reset()
+ {
+ if (this.startup == StartupCondition.ColdStart)
+ {
+ this.IRQ.Raise();
+ this.RTS.Raise();
+ }
+
+ this.statusRDRF = false;
+ this.statusTDRE = true;
+ this.statusOVRN = false;
+ this.DCD.Lower();
+ this.startup = StartupCondition.WarmStart;
+ this.statusRead = false;
+ }
+
+ private void StartTransmit()
+ {
+ this.TDR = this.DATA;
+ this.statusTDRE = false;
+ this.OnTransmitting();
+ }
+
+ private void CompleteReceive()
+ {
+ this.DATA = this.RDR;
+ this.statusOVRN = this.statusRDRF = false; // Any existing data overrun is now moot.
+ this.OnReceived();
+ }
+ }
+}
\ No newline at end of file
diff --git a/MC6850/MC6850.csproj b/MC6850/MC6850.csproj
new file mode 100644
index 0000000..391382c
--- /dev/null
+++ b/MC6850/MC6850.csproj
@@ -0,0 +1,66 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}
+ Library
+ Properties
+ EightBit
+ MC6850
+ v4.7.2
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ latest
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ latest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {6ebf8857-62a3-4ef4-af21-c1844031d7e4}
+ EightBit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MC6850/Properties/AssemblyInfo.cs b/MC6850/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b421855
--- /dev/null
+++ b/MC6850/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MC6850")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MC6850")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a9760efd-79f2-4ec3-8647-d2a1587e3e7e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MC6850/packages.config b/MC6850/packages.config
new file mode 100644
index 0000000..2c95c37
--- /dev/null
+++ b/MC6850/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/MC6850/stylecop.json b/MC6850/stylecop.json
new file mode 100644
index 0000000..3af08b4
--- /dev/null
+++ b/MC6850/stylecop.json
@@ -0,0 +1,19 @@
+{
+ // ACTION REQUIRED: This file was automatically added to your project, but it
+ // will not take effect until additional steps are taken to enable it. See the
+ // following page for additional information:
+ //
+ // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
+
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "documentInterfaces": false,
+ "documentExposedElements": false,
+ "documentInternalElements": false,
+ "documentPrivateElements": false,
+ "documentPrivateFields": false,
+ "companyName": "Adrian Conlon"
+ }
+ }
+}