mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-04 18:29:40 +00:00
Adds an attempt to clock the AY.
This commit is contained in:
parent
f7e66dea61
commit
f602f9b6ec
@ -62,6 +62,38 @@ class InterruptTimer {
|
|||||||
int timer_;
|
int timer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AYDeferrer {
|
||||||
|
public:
|
||||||
|
inline void setup_output() {
|
||||||
|
ay_.reset(new GI::AY38910);
|
||||||
|
ay_->set_input_rate(1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void close_output() {
|
||||||
|
ay_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void run_for(HalfCycles half_cycles) {
|
||||||
|
cycles_since_update_ += half_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void flush() {
|
||||||
|
ay_->run_for(cycles_since_update_.divide_cycles(Cycles(4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Outputs::Speaker> get_speaker() {
|
||||||
|
return ay_;
|
||||||
|
}
|
||||||
|
|
||||||
|
GI::AY38910 *ay() {
|
||||||
|
return ay_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<GI::AY38910> ay_;
|
||||||
|
HalfCycles cycles_since_update_;
|
||||||
|
};
|
||||||
|
|
||||||
class CRTCBusHandler {
|
class CRTCBusHandler {
|
||||||
public:
|
public:
|
||||||
CRTCBusHandler(uint8_t *ram, InterruptTimer &interrupt_timer) :
|
CRTCBusHandler(uint8_t *ram, InterruptTimer &interrupt_timer) :
|
||||||
@ -301,13 +333,14 @@ struct KeyboardState {
|
|||||||
|
|
||||||
class i8255PortHandler : public Intel::i8255::PortHandler {
|
class i8255PortHandler : public Intel::i8255::PortHandler {
|
||||||
public:
|
public:
|
||||||
i8255PortHandler(const KeyboardState &key_state, const CRTCBusHandler &crtc_bus_handler) :
|
i8255PortHandler(const KeyboardState &key_state, const CRTCBusHandler &crtc_bus_handler, AYDeferrer &ay) :
|
||||||
key_state_(key_state), crtc_bus_handler_(crtc_bus_handler) {}
|
key_state_(key_state), crtc_bus_handler_(crtc_bus_handler), ay_(ay) {}
|
||||||
|
|
||||||
void set_value(int port, uint8_t value) {
|
void set_value(int port, uint8_t value) {
|
||||||
switch(port) {
|
switch(port) {
|
||||||
case 0:
|
case 0:
|
||||||
ay_->set_data_input(value);
|
ay_.flush();
|
||||||
|
ay_.ay()->set_data_input(value);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// printf("Vsync, etc: %02x\n", value);
|
// printf("Vsync, etc: %02x\n", value);
|
||||||
@ -316,13 +349,13 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
|||||||
// TODO: the AY really should allow port communications to be active. Work needed.
|
// TODO: the AY really should allow port communications to be active. Work needed.
|
||||||
int key_row = value & 15;
|
int key_row = value & 15;
|
||||||
if(key_row < 10) {
|
if(key_row < 10) {
|
||||||
ay_->set_port_input(false, key_state_.rows[key_row]);
|
ay_.ay()->set_port_input(false, key_state_.rows[key_row]);
|
||||||
} else {
|
} else {
|
||||||
ay_->set_port_input(false, 0xff);
|
ay_.ay()->set_port_input(false, 0xff);
|
||||||
}
|
}
|
||||||
// TODO: set casette motor control: ((value >> 4) & 1)
|
// TODO: set casette motor control: ((value >> 4) & 1)
|
||||||
// TODO: set casette output: ((value >> 5) & 1)
|
// TODO: set casette output: ((value >> 5) & 1)
|
||||||
ay_->set_control_lines(
|
ay_.ay()->set_control_lines(
|
||||||
(GI::AY38910::ControlLines)(
|
(GI::AY38910::ControlLines)(
|
||||||
((value & 0x80) ? GI::AY38910::BDIR : 0) |
|
((value & 0x80) ? GI::AY38910::BDIR : 0) |
|
||||||
((value & 0x40) ? GI::AY38910::BC1 : 0) |
|
((value & 0x40) ? GI::AY38910::BC1 : 0) |
|
||||||
@ -334,7 +367,7 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
|||||||
|
|
||||||
uint8_t get_value(int port) {
|
uint8_t get_value(int port) {
|
||||||
switch(port) {
|
switch(port) {
|
||||||
case 0: return ay_->get_data_output();
|
case 0: return ay_.ay()->get_data_output();
|
||||||
case 1: return (crtc_bus_handler_.get_vsync() ? 1 : 0) | 0xfe;
|
case 1: return (crtc_bus_handler_.get_vsync() ? 1 : 0) | 0xfe;
|
||||||
case 2:
|
case 2:
|
||||||
// printf("[In] Key row, etc\n");
|
// printf("[In] Key row, etc\n");
|
||||||
@ -343,12 +376,8 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
|||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_ay(std::shared_ptr<GI::AY38910> ay) {
|
|
||||||
ay_ = ay;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<GI::AY38910> ay_;
|
AYDeferrer &ay_;
|
||||||
const KeyboardState &key_state_;
|
const KeyboardState &key_state_;
|
||||||
const CRTCBusHandler &crtc_bus_handler_;
|
const CRTCBusHandler &crtc_bus_handler_;
|
||||||
};
|
};
|
||||||
@ -362,7 +391,7 @@ class ConcreteMachine:
|
|||||||
crtc_(crtc_bus_handler_),
|
crtc_(crtc_bus_handler_),
|
||||||
crtc_bus_handler_(ram_, interrupt_timer_),
|
crtc_bus_handler_(ram_, interrupt_timer_),
|
||||||
i8255_(i8255_port_handler_),
|
i8255_(i8255_port_handler_),
|
||||||
i8255_port_handler_(key_state_, crtc_bus_handler_) {
|
i8255_port_handler_(key_state_, crtc_bus_handler_, ay_) {
|
||||||
// primary clock is 4Mhz
|
// primary clock is 4Mhz
|
||||||
set_clock_rate(4000000);
|
set_clock_rate(4000000);
|
||||||
}
|
}
|
||||||
@ -381,6 +410,9 @@ class ConcreteMachine:
|
|||||||
if(crtc_cycles) crtc_.run_for(Cycles(1));
|
if(crtc_cycles) crtc_.run_for(Cycles(1));
|
||||||
set_interrupt_line(interrupt_timer_.get_request());
|
set_interrupt_line(interrupt_timer_.get_request());
|
||||||
|
|
||||||
|
// Pump the AY.
|
||||||
|
ay_.run_for(cycle.length);
|
||||||
|
|
||||||
// Stop now if no action is strictly required.
|
// Stop now if no action is strictly required.
|
||||||
if(!cycle.is_terminal()) return HalfCycles(0);
|
if(!cycle.is_terminal()) return HalfCycles(0);
|
||||||
|
|
||||||
@ -455,18 +487,17 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void flush() {
|
void flush() {
|
||||||
// i8255_port_handler_.flush();
|
ay_.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_output(float aspect_ratio) {
|
void setup_output(float aspect_ratio) {
|
||||||
crtc_bus_handler_.setup_output(aspect_ratio);
|
crtc_bus_handler_.setup_output(aspect_ratio);
|
||||||
ay_.reset(new GI::AY38910);
|
ay_.setup_output();
|
||||||
i8255_port_handler_.set_ay(ay_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_output() {
|
void close_output() {
|
||||||
crtc_bus_handler_.close_output();
|
crtc_bus_handler_.close_output();
|
||||||
ay_.reset();
|
ay_.close_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Outputs::CRT::CRT> get_crt() {
|
std::shared_ptr<Outputs::CRT::CRT> get_crt() {
|
||||||
@ -474,7 +505,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Outputs::Speaker> get_speaker() {
|
std::shared_ptr<Outputs::Speaker> get_speaker() {
|
||||||
return ay_;
|
return ay_.get_speaker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_for(const Cycles cycles) {
|
void run_for(const Cycles cycles) {
|
||||||
@ -517,7 +548,7 @@ class ConcreteMachine:
|
|||||||
CRTCBusHandler crtc_bus_handler_;
|
CRTCBusHandler crtc_bus_handler_;
|
||||||
Motorola::CRTC::CRTC6845<CRTCBusHandler> crtc_;
|
Motorola::CRTC::CRTC6845<CRTCBusHandler> crtc_;
|
||||||
|
|
||||||
std::shared_ptr<GI::AY38910> ay_;
|
AYDeferrer ay_;
|
||||||
i8255PortHandler i8255_port_handler_;
|
i8255PortHandler i8255_port_handler_;
|
||||||
Intel::i8255::i8255<i8255PortHandler> i8255_;
|
Intel::i8255::i8255<i8255PortHandler> i8255_;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user