summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelodi <62381002+Melodi17@users.noreply.github.com>2026-03-18 07:19:22 +1000
committerMelodi <62381002+Melodi17@users.noreply.github.com>2026-03-18 07:19:22 +1000
commit0bb62fc65526a0981cd328dea1b09aba8ce0a576 (patch)
treea601bb87ead0f58674ee18088e9e41e77512d3b8
parent203331522e22c778ff830c3c6cf4f439778939fa (diff)
add: Add bus
-rw-r--r--Q1.core/Arch/AddressingModes.cs2
-rw-r--r--Q1.core/Arch/Chip.cs2
-rw-r--r--Q1.core/Components/Bus.cs100
-rw-r--r--Q1.core/Components/IAddressable.cs (renamed from Q1.core/IAddressable.cs)17
-rw-r--r--Q1.core/Components/Memory.cs21
-rw-r--r--Q1.core/Memory.cs15
6 files changed, 135 insertions, 22 deletions
diff --git a/Q1.core/Arch/AddressingModes.cs b/Q1.core/Arch/AddressingModes.cs
index 206ee4f..96b4475 100644
--- a/Q1.core/Arch/AddressingModes.cs
+++ b/Q1.core/Arch/AddressingModes.cs
@@ -1,5 +1,7 @@
namespace Q1.core.Arch;
+using Components;
+
public static class AddressingModes
{
public static AddressingMode[] Lookup = new AddressingMode[8];
diff --git a/Q1.core/Arch/Chip.cs b/Q1.core/Arch/Chip.cs
index 69a0877..9f5f109 100644
--- a/Q1.core/Arch/Chip.cs
+++ b/Q1.core/Arch/Chip.cs
@@ -1,5 +1,7 @@
namespace Q1.core.Arch;
+using Components;
+
// Big endian
public class Chip
{
diff --git a/Q1.core/Components/Bus.cs b/Q1.core/Components/Bus.cs
new file mode 100644
index 0000000..02b20a7
--- /dev/null
+++ b/Q1.core/Components/Bus.cs
@@ -0,0 +1,100 @@
+namespace Q1.core.Components;
+
+using Q1.core.Arch;
+
+public class Bus : IAddressable
+{
+ private Chip? _chip;
+ private readonly List<IAddressable> _devices;
+
+ public u16 AddressableStart { get; }
+ public u16 AddressableEnd { get; }
+
+ public Bus(u16 addressableStart, u16 addressableEnd)
+ {
+ this.AddressableStart = addressableStart;
+ this.AddressableEnd = addressableEnd;
+ this._devices = new();
+ }
+
+ public void SendInterrupt(u16 code)
+ {
+ if (this._chip == null)
+ throw new InvalidOperationException("Chip is not attached to bus");
+
+ this._chip.Interrupt(code);
+ }
+
+ public void AttachChip(Chip chip)
+ {
+ if (this._chip != null)
+ throw new InvalidOperationException("Bus already has a chip attached.");
+
+ this._chip = chip;
+ chip.Bus = this;
+ }
+
+ public void MountDevice(IAddressable device)
+ {
+ if (device.AddressableStart >= device.AddressableEnd)
+ throw new ArgumentException("Addressable range is invalid.", nameof(device));
+
+ int index = 0;
+ while (index < this._devices.Count && this._devices[index].AddressableStart < device.AddressableStart)
+ index++;
+
+ if (index > 0)
+ {
+ IAddressable prev = this._devices[index - 1];
+ if (device.AddressableStart < prev.AddressableEnd)
+ throw new InvalidOperationException("Address range overlaps with previous device.");
+ }
+
+ if (index < this._devices.Count)
+ {
+ IAddressable next = this._devices[index];
+ if (device.AddressableEnd > next.AddressableStart)
+ throw new InvalidOperationException("Address range overlaps with next device.");
+ }
+
+ this._devices.Insert(index, device);
+ }
+
+ private IAddressable? GetDevice(u16 address)
+ {
+ foreach (IAddressable device in this._devices)
+ {
+ if (address < device.AddressableStart)
+ break;
+
+ if (address < device.AddressableEnd)
+ return device;
+ }
+
+ return null;
+ }
+
+ public u8 Read(u16 address)
+ {
+ IAddressable? device = this.GetDevice(address);
+ if (device == null)
+ return 0;
+
+ return device.Read((u16) (address - device.AddressableStart));
+ }
+
+ public void Write(u16 address, u8 value)
+ {
+ IAddressable? device = this.GetDevice(address);
+ if (device == null)
+ return;
+
+ device.Write((u16) (address - device.AddressableStart), value);
+ }
+
+ public void Clock()
+ {
+ foreach (IAddressable addressable in this._devices)
+ addressable.Clock();
+ }
+} \ No newline at end of file
diff --git a/Q1.core/IAddressable.cs b/Q1.core/Components/IAddressable.cs
index 49a697e..54218d9 100644
--- a/Q1.core/IAddressable.cs
+++ b/Q1.core/Components/IAddressable.cs
@@ -1,10 +1,13 @@
-namespace Q1.core;
+namespace Q1.core.Components;
public interface IAddressable
{
public u8 Read(u16 address);
public void Write(u16 address, u8 value);
public void Clock();
+
+ public u16 AddressableStart { get; }
+ public u16 AddressableEnd { get; }
}
public static class AddressableExtensions
@@ -12,15 +15,15 @@ public static class AddressableExtensions
public static u16 ReadWord(this IAddressable bus, u16 address)
{
u8 high = bus.Read(address);
- u8 low = bus.Read((u16)(address + 1));
- return (u16)((high << 8) | low);
+ u8 low = bus.Read((u16) (address + 1));
+ return (u16) ((high << 8) | low);
}
-
+
public static void WriteWord(this IAddressable bus, u16 address, u16 value)
{
- u8 high = (u8) (value & 0xFF);
- u8 low = (u8)((value >> 8) & 0xFF);
+ u8 high = (u8) (value & 0xFF);
+ u8 low = (u8) ((value >> 8) & 0xFF);
bus.Write(address, low);
- bus.Write((u16)(address + 1), high);
+ bus.Write((u16) (address + 1), high);
}
} \ No newline at end of file
diff --git a/Q1.core/Components/Memory.cs b/Q1.core/Components/Memory.cs
new file mode 100644
index 0000000..9d23c7a
--- /dev/null
+++ b/Q1.core/Components/Memory.cs
@@ -0,0 +1,21 @@
+namespace Q1.core.Components;
+
+public class Memory : IAddressable
+{
+ private readonly u8[] _memory;
+
+ public u16 AddressableStart { get; }
+ public u16 AddressableEnd { get; }
+
+ public Memory(u16 start, u16 size)
+ {
+ this.AddressableStart = start;
+ this.AddressableEnd = (u16) (start + size);
+
+ this._memory = new u8[size];
+ }
+
+ public u8 Read(u16 address) => this._memory[address];
+ public void Write(u16 address, u8 value) => this._memory[address] = value;
+ public void Clock() { /* No timing behavior for simple memory */ }
+} \ No newline at end of file
diff --git a/Q1.core/Memory.cs b/Q1.core/Memory.cs
deleted file mode 100644
index d140809..0000000
--- a/Q1.core/Memory.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Q1.core;
-
-public class Memory : IAddressable
-{
- private readonly u8[] _memory;
-
- public Memory(int size)
- {
- _memory = new u8[size];
- }
-
- public u8 Read(u16 address) => _memory[address];
- public void Write(u16 address, u8 value) => _memory[address] = value;
- public void Clock() { /* No timing behavior for simple memory */ }
-} \ No newline at end of file