Skip to main content

mc6809_core/
bus.rs

1//   Copyright 2026 Martin Åkesson
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15/// Interrupt and control signals returned by [`Bus::tick`].
16///
17/// Each field corresponds to a physical input pin on the 6809 CPU.
18/// The default is all signals de-asserted (inactive).
19#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
20pub struct BusSignals {
21    /// IRQ line state (active = asserted, level-triggered).
22    pub irq: bool,
23    /// FIRQ line state (active = asserted, level-triggered).
24    pub firq: bool,
25    /// NMI request (edge-triggered — set `true` to trigger once).
26    pub nmi: bool,
27    /// Request the CPU to halt (e.g. watchdog expiry).
28    pub halt: bool,
29}
30
31/// Bus trait for the 6809 CPU.
32///
33/// Peripherals that need to advance with CPU time should implement [`tick`](Bus::tick)
34/// and return the appropriate [`BusSignals`] to drive the CPU's interrupt lines.
35pub trait Bus {
36    /// Advance peripherals by `cycles` CPU cycles and return interrupt/control signals.
37    ///
38    /// Called once after each CPU step (or batch of steps). Implementations
39    /// should update timers, trigger IRQs, etc. and report the resulting
40    /// signal states. The caller is responsible for feeding these signals
41    /// into the CPU via [`crate::Cpu::set_irq`], [`crate::Cpu::set_firq`], etc.
42    ///
43    /// The default implementation is a no-op that returns all signals inactive,
44    /// which is correct for simple test buses with no peripherals.
45    fn tick(&mut self, _cycles: u64) -> BusSignals {
46        BusSignals::default()
47    }
48}
49
50/// Memory trait for the 6809 CPU.
51///
52/// Implement this trait to provide the CPU with access to memory and I/O.
53/// The 6809 has a 16-bit address bus (64KB address space) and an 8-bit data bus.
54pub trait Memory {
55    /// Read a byte from the given address.
56    fn read(&mut self, addr: u16) -> u8;
57
58    /// Write a byte to the given address.
59    fn write(&mut self, addr: u16, val: u8);
60
61    /// Read a big-endian 16-bit word (high byte at `addr`, low byte at `addr + 1`).
62    fn read_word(&mut self, addr: u16) -> u16 {
63        let hi = self.read(addr) as u16;
64        let lo = self.read(addr.wrapping_add(1)) as u16;
65        (hi << 8) | lo
66    }
67
68    /// Write a big-endian 16-bit word (high byte at `addr`, low byte at `addr + 1`).
69    fn write_word(&mut self, addr: u16, val: u16) {
70        self.write(addr, (val >> 8) as u8);
71        self.write(addr.wrapping_add(1), val as u8);
72    }
73}