2016-07-10 12:05:05 +00:00
|
|
|
//
|
2016-06-07 01:56:02 +00:00
|
|
|
// 6522.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 06/06/2016.
|
2018-05-13 19:19:52 +00:00
|
|
|
// Copyright 2016 Thomas Harte. All rights reserved.
|
2016-06-07 01:56:02 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef _522_hpp
|
|
|
|
#define _522_hpp
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
#include "Implementation/6522Storage.hpp"
|
|
|
|
|
2017-07-27 12:05:14 +00:00
|
|
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
|
|
|
|
2016-06-07 01:56:02 +00:00
|
|
|
namespace MOS {
|
2017-09-04 18:26:04 +00:00
|
|
|
namespace MOS6522 {
|
2016-06-07 01:56:02 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
enum Port {
|
|
|
|
A = 0,
|
|
|
|
B = 1
|
|
|
|
};
|
2016-06-19 22:11:37 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
enum Line {
|
|
|
|
One = 0,
|
|
|
|
Two = 1
|
|
|
|
};
|
2016-06-10 02:37:59 +00:00
|
|
|
|
2017-09-04 18:32:34 +00:00
|
|
|
/*!
|
|
|
|
Provides the mechanism for just-int-time communication from a 6522; the normal use case is to compose a
|
|
|
|
6522 and a subclass of PortHandler in order to reproduce a 6522 and its original bus wiring.
|
|
|
|
*/
|
2017-09-04 18:26:04 +00:00
|
|
|
class PortHandler {
|
2016-06-07 01:56:02 +00:00
|
|
|
public:
|
2017-09-04 18:32:34 +00:00
|
|
|
/// Requests the current input value of @c port from the port handler.
|
2021-07-18 15:29:26 +00:00
|
|
|
uint8_t get_port_input([[maybe_unused]] Port port) {
|
|
|
|
return 0xff;
|
|
|
|
}
|
2017-09-04 18:32:34 +00:00
|
|
|
|
|
|
|
/// Sets the current output value of @c port and provides @c direction_mask, indicating which pins are marked as output.
|
2021-07-18 15:29:26 +00:00
|
|
|
void set_port_output([[maybe_unused]] Port port, [[maybe_unused]] uint8_t value, [[maybe_unused]] uint8_t direction_mask) {}
|
2017-09-04 18:32:34 +00:00
|
|
|
|
|
|
|
/// Sets the current logical output level for line @c line on port @c port.
|
2021-07-18 15:29:26 +00:00
|
|
|
void set_control_line_output([[maybe_unused]] Port port, [[maybe_unused]] Line line, [[maybe_unused]] bool value) {}
|
2017-09-04 18:32:34 +00:00
|
|
|
|
|
|
|
/// Sets the current logical value of the interrupt line.
|
2021-07-18 15:29:26 +00:00
|
|
|
void set_interrupt_status([[maybe_unused]] bool status) {}
|
2019-06-01 18:39:40 +00:00
|
|
|
|
|
|
|
/// Provides a measure of time elapsed between other calls.
|
2021-07-18 15:29:26 +00:00
|
|
|
void run_for([[maybe_unused]] HalfCycles duration) {}
|
2019-06-01 18:39:40 +00:00
|
|
|
|
|
|
|
/// Receives passed-on flush() calls from the 6522.
|
2021-07-18 15:29:26 +00:00
|
|
|
void flush() {}
|
2017-09-04 18:26:04 +00:00
|
|
|
};
|
2016-06-26 16:30:01 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
/*!
|
2017-09-04 18:32:34 +00:00
|
|
|
Provided as an optional alternative base to @c PortHandler for port handlers; via the delegate pattern adds
|
|
|
|
a virtual level of indirection for receiving changes to the interrupt line.
|
2017-09-04 18:26:04 +00:00
|
|
|
*/
|
|
|
|
class IRQDelegatePortHandler: public PortHandler {
|
|
|
|
public:
|
|
|
|
class Delegate {
|
|
|
|
public:
|
2017-09-04 18:32:34 +00:00
|
|
|
/// Indicates that the interrupt status has changed for the IRQDelegatePortHandler provided.
|
|
|
|
virtual void mos6522_did_change_interrupt_status(void *irq_delegate) = 0;
|
2016-06-26 20:32:27 +00:00
|
|
|
};
|
|
|
|
|
2017-09-04 18:32:34 +00:00
|
|
|
/// Sets the delegate that will receive notification of changes in the interrupt line.
|
2017-09-04 18:26:04 +00:00
|
|
|
void set_interrupt_delegate(Delegate *delegate);
|
2017-09-04 18:32:34 +00:00
|
|
|
|
|
|
|
/// Overrides PortHandler::set_interrupt_status, notifying the delegate if one is set.
|
2017-09-04 18:26:04 +00:00
|
|
|
void set_interrupt_status(bool new_status);
|
2016-06-11 11:12:55 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
private:
|
|
|
|
Delegate *delegate_ = nullptr;
|
|
|
|
};
|
2016-10-28 01:06:31 +00:00
|
|
|
|
2016-06-19 22:11:37 +00:00
|
|
|
/*!
|
2017-09-04 18:26:04 +00:00
|
|
|
Implements a template for emulation of the MOS 6522 Versatile Interface Adaptor ('VIA').
|
|
|
|
|
|
|
|
The VIA provides:
|
|
|
|
* two timers, each of which may trigger interrupts and one of which may repeat;
|
|
|
|
* two digial input/output ports; and
|
|
|
|
* a serial-to-parallel shifter.
|
|
|
|
|
|
|
|
Consumers should derive their own curiously-recurring-template-pattern subclass,
|
|
|
|
implementing bus communications as required.
|
2016-06-19 22:11:37 +00:00
|
|
|
*/
|
2021-07-18 15:28:18 +00:00
|
|
|
template <class BusHandlerT> class MOS6522: public MOS6522Storage {
|
2016-06-18 12:51:18 +00:00
|
|
|
public:
|
2021-07-18 15:28:18 +00:00
|
|
|
MOS6522(BusHandlerT &bus_handler) noexcept : bus_handler_(bus_handler) {}
|
2017-09-06 01:21:23 +00:00
|
|
|
MOS6522(const MOS6522 &) = delete;
|
2016-06-18 12:51:18 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
/*! Sets a register value. */
|
2020-01-05 18:40:02 +00:00
|
|
|
void write(int address, uint8_t value);
|
2016-06-18 12:51:18 +00:00
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
/*! Gets a register value. */
|
2020-01-05 18:40:02 +00:00
|
|
|
uint8_t read(int address);
|
2016-06-18 12:51:18 +00:00
|
|
|
|
2018-05-12 02:24:33 +00:00
|
|
|
/*! @returns the bus handler. */
|
2021-07-18 15:28:18 +00:00
|
|
|
BusHandlerT &bus_handler();
|
2018-05-12 02:24:33 +00:00
|
|
|
|
2019-05-08 16:35:17 +00:00
|
|
|
/// Sets the input value of line @c line on port @c port.
|
|
|
|
void set_control_line_input(Port port, Line line, bool value);
|
|
|
|
|
|
|
|
/// Runs for a specified number of half cycles.
|
|
|
|
void run_for(const HalfCycles half_cycles);
|
|
|
|
|
|
|
|
/// Runs for a specified number of cycles.
|
|
|
|
void run_for(const Cycles cycles);
|
|
|
|
|
|
|
|
/// @returns @c true if the IRQ line is currently active; @c false otherwise.
|
2020-05-10 01:22:51 +00:00
|
|
|
bool get_interrupt_line() const;
|
2019-05-08 16:35:17 +00:00
|
|
|
|
2019-06-01 18:39:40 +00:00
|
|
|
/// Updates the port handler to the current time and then requests that it flush.
|
|
|
|
void flush();
|
|
|
|
|
2016-06-18 12:51:18 +00:00
|
|
|
private:
|
2019-05-08 16:35:17 +00:00
|
|
|
void do_phase1();
|
|
|
|
void do_phase2();
|
2019-05-08 18:54:40 +00:00
|
|
|
void shift_in();
|
|
|
|
void shift_out();
|
2019-06-01 18:39:40 +00:00
|
|
|
|
2021-07-18 15:28:18 +00:00
|
|
|
BusHandlerT &bus_handler_;
|
2019-06-01 18:39:40 +00:00
|
|
|
HalfCycles time_since_bus_handler_call_;
|
2017-09-04 18:26:04 +00:00
|
|
|
|
2019-05-08 16:48:29 +00:00
|
|
|
void access(int address);
|
|
|
|
|
2020-09-20 18:51:59 +00:00
|
|
|
uint8_t get_port_input(Port port, uint8_t output_mask, uint8_t output, uint8_t timer_mask);
|
2017-09-04 18:26:04 +00:00
|
|
|
inline void reevaluate_interrupts();
|
2019-05-08 17:33:22 +00:00
|
|
|
|
|
|
|
/// Sets the current intended output value for the port and line;
|
|
|
|
/// if this affects the visible output, it will be passed to the handler.
|
2019-06-10 13:28:27 +00:00
|
|
|
void set_control_line_output(Port port, Line line, LineState value);
|
|
|
|
void evaluate_cb2_output();
|
2020-09-20 19:03:26 +00:00
|
|
|
void evaluate_port_b_output();
|
2016-06-18 12:51:18 +00:00
|
|
|
};
|
|
|
|
|
2017-09-04 18:26:04 +00:00
|
|
|
}
|
2016-06-07 01:56:02 +00:00
|
|
|
}
|
|
|
|
|
2019-03-02 23:07:05 +00:00
|
|
|
#include "Implementation/6522Implementation.hpp"
|
|
|
|
|
2016-06-07 01:56:02 +00:00
|
|
|
#endif /* _522_hpp */
|