1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-26 15:32:04 +00:00

The 6522 is now a ClockReceiver.

This commit is contained in:
Thomas Harte 2017-07-24 22:29:09 -04:00
parent 2912d7055b
commit efdac2ce8c
5 changed files with 25 additions and 37 deletions

View File

@ -13,6 +13,8 @@
#include <typeinfo>
#include <cstdio>
#include "../ClockReceiver.hpp"
namespace MOS {
/*!
@ -26,7 +28,7 @@ namespace MOS {
Consumers should derive their own curiously-recurring-template-pattern subclass,
implementing bus communications as required.
*/
template <class T> class MOS6522 {
template <class T> class MOS6522: public ClockReceiver<MOS6522<T>> {
private:
enum InterruptFlag: uint8_t {
CA2ActiveEdge = 1 << 0,
@ -250,32 +252,22 @@ template <class T> class MOS6522 {
timer_is_running_[0] = false;\
}
/*!
Runs for a specified number of half cycles.
/*! Runs for a specified number of half cycles. */
inline void run_for(const HalfCycles &half_cycles) {
int number_of_half_cycles = half_cycles.as_int();
Although the original chip accepts only a phase-2 input, timer reloads are specified as occuring
1.5 cycles after the timer hits zero. It therefore may be necessary to emulate at half-cycle precision.
The first emulated half-cycle will be the period between the trailing edge of a phase-2 input and the
next rising edge. So it should align with a full system's phase-1. The next emulated half-cycle will be
that which occurs during phase-2.
Callers should decide whether they are going to use @c run_for_half_cycles or @c run_for_cycles, and not
intermingle usage.
*/
inline void run_for_half_cycles(unsigned int number_of_cycles) {
if(is_phase2_) {
phase2();
number_of_cycles--;
number_of_half_cycles--;
}
while(number_of_cycles >= 2) {
while(number_of_half_cycles >= 2) {
phase1();
phase2();
number_of_cycles -= 2;
number_of_half_cycles -= 2;
}
if(number_of_cycles) {
if(number_of_half_cycles) {
phase1();
is_phase2_ = true;
} else {
@ -283,13 +275,9 @@ template <class T> class MOS6522 {
}
}
/*!
Runs for a specified number of cycles.
Callers should decide whether they are going to use @c run_for_half_cycles or @c run_for_cycles, and not
intermingle usage.
*/
inline void run_for_cycles(unsigned int number_of_cycles) {
/*! Runs for a specified number of cycles. */
inline void run_for(const Cycles &cycles) {
int number_of_cycles = cycles.as_int();
while(number_of_cycles--) {
phase1();
phase2();

View File

@ -63,8 +63,8 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
drive_VIA_.set_register(address, *value);
}
serial_port_VIA_->run_for_cycles(1);
drive_VIA_.run_for_cycles(1);
serial_port_VIA_->run_for(Cycles(1));
drive_VIA_.run_for(Cycles(1));
return 1;
}

View File

@ -179,8 +179,8 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
}
}
user_port_via_->run_for_cycles(1);
keyboard_via_->run_for_cycles(1);
user_port_via_->run_for(Cycles(1));
keyboard_via_->run_for(Cycles(1));
if(typer_ && operation == CPU::MOS6502::BusOperation::ReadOpcode && address == 0xEB1E) {
if(!typer_->type_next_character()) {
clear_all_keys();

View File

@ -130,7 +130,7 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
}
}
via_.run_for_cycles(1);
via_.run_for(Cycles(1));
if(microdisc_is_enabled_) microdisc_.run_for(Cycles(8));
cycles_since_video_update_++;
return 1;
@ -235,15 +235,15 @@ uint8_t Machine::VIA::get_port_input(Port port) {
}
void Machine::VIA::flush() {
ay8910->run_for(Cycles((int)cycles_since_ay_update_));
ay8910->run_for(Cycles(cycles_since_ay_update_));
ay8910->flush();
cycles_since_ay_update_ = 0;
}
void Machine::VIA::run_for_cycles(unsigned int number_of_cycles) {
cycles_since_ay_update_ += number_of_cycles;
MOS::MOS6522<VIA>::run_for_cycles(number_of_cycles);
tape->run_for(Cycles((int)number_of_cycles));
void Machine::VIA::run_for(const Cycles &cycles) {
cycles_since_ay_update_ += cycles.as_int();
MOS::MOS6522<VIA>::run_for(cycles);
tape->run_for(cycles);
}
void Machine::VIA::update_ay() {

View File

@ -143,7 +143,7 @@ class Machine:
void set_control_line_output(Port port, Line line, bool value);
void set_port_output(Port port, uint8_t value, uint8_t direction_mask);
uint8_t get_port_input(Port port);
inline void run_for_cycles(unsigned int number_of_cycles);
inline void run_for(const Cycles &cycles);
std::shared_ptr<GI::AY38910> ay8910;
std::unique_ptr<TapePlayer> tape;
@ -154,7 +154,7 @@ class Machine:
private:
void update_ay();
bool ay_bdir_, ay_bc1_;
unsigned int cycles_since_ay_update_;
int cycles_since_ay_update_;
};
VIA via_;
std::shared_ptr<Keyboard> keyboard_;