1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-18 13:29:41 +00:00
CLK/Components/6526/6526.hpp

90 lines
2.4 KiB
C++
Raw Normal View History

2021-07-18 15:36:13 +00:00
//
// 6526.h
// Clock Signal
//
// Created by Thomas Harte on 18/07/2021.
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#pragma once
2021-07-18 15:36:13 +00:00
#include <cstdint>
#include "Implementation/6526Storage.hpp"
#include "../Serial/Line.hpp"
2023-05-10 21:02:18 +00:00
namespace MOS::MOS6526 {
2021-07-18 15:36:13 +00:00
enum Port {
A = 0,
B = 1
};
2021-07-18 15:36:13 +00:00
struct PortHandler {
2021-07-19 00:25:04 +00:00
/// Requests the current input value of @c port from the port handler.
uint8_t get_port_input([[maybe_unused]] Port port) {
return 0xff;
}
/// Sets the current output value of @c port; any bits marked as input will be supplied as 1s.
void set_port_output([[maybe_unused]] Port port, [[maybe_unused]] uint8_t value) {}
2021-07-18 15:36:13 +00:00
};
enum class Personality {
// The 6526, used in machines such as the C64, has a BCD time-of-day clock.
P6526,
2021-07-18 15:36:13 +00:00
// The 8250, used in the Amiga, provides a binary time-of-day clock.
P8250,
2021-07-18 15:36:13 +00:00
};
template <typename PortHandlerT, Personality personality> class MOS6526:
2021-11-07 13:18:54 +00:00
private MOS6526Storage,
private Serial::Line<true>::ReadDelegate
{
2021-07-18 15:36:13 +00:00
public:
2021-11-07 13:18:54 +00:00
MOS6526(PortHandlerT &port_handler) noexcept : port_handler_(port_handler) {
serial_input.set_read_delegate(this);
}
MOS6526(const MOS6526 &) = delete;
2021-07-18 15:36:13 +00:00
/// Writes @c value to the register at @c address. Only the low two bits of the address are decoded.
void write(int address, uint8_t value);
/// Fetches the value of the register @c address. Only the low two bits of the address are decoded.
uint8_t read(int address);
/// Pulses Phi2 to advance by the specified number of half cycles.
void run_for(const HalfCycles half_cycles);
/// Pulses the TOD input the specified number of times.
void advance_tod(int count);
2021-07-28 23:36:30 +00:00
/// @returns @c true if the interrupt output is active, @c false otherwise.
bool get_interrupt_line();
2021-08-04 02:19:41 +00:00
/// Sets the current state of the CNT input.
void set_cnt_input(bool active);
/// Provides both the serial input bit and an additional source of CNT.
Serial::Line<true> serial_input;
2021-10-09 11:08:59 +00:00
/// Sets the current state of the FLG input.
void set_flag_input(bool low);
private:
PortHandlerT &port_handler_;
TODStorage<personality == Personality::P8250> tod_;
template <int port> void set_port_output();
2021-07-19 00:25:04 +00:00
template <int port> uint8_t get_port_input();
void update_interrupts();
2021-07-24 01:58:52 +00:00
void posit_interrupt(uint8_t mask);
void advance_counters(int);
2021-11-07 13:18:54 +00:00
bool serial_line_did_produce_bit(Serial::Line<true> *line, int bit) final;
2021-07-18 15:36:13 +00:00
};
}
#include "Implementation/6526Implementation.hpp"