From 516d78f5a890c99815335ef0171301555bf59eef Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 12 Oct 2019 23:46:57 -0400 Subject: [PATCH] Attempts to implement transmission interrupts and ClockingHint::Source. --- Components/6850/6850.cpp | 32 +++++++++++++++++++++++++------- Components/6850/6850.hpp | 9 ++++++++- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Components/6850/6850.cpp b/Components/6850/6850.cpp index f86989c5d..e935590ff 100644 --- a/Components/6850/6850.cpp +++ b/Components/6850/6850.cpp @@ -18,12 +18,14 @@ ACIA::ACIA() {} uint8_t ACIA::read(int address) { if(address&1) { LOG("Read from receive register"); + interrupt_request_ = false; } else { LOG("Read status"); return ((next_transmission_ == NoTransmission) ? 0x02 : 0x00) | (data_carrier_detect.read() ? 0x04 : 0x00) | - (clear_to_send.read() ? 0x08 : 0x00) + (clear_to_send.read() ? 0x08 : 0x00) | + (interrupt_request_ ? 0x80 : 0x00) ; // b0: receive data full. @@ -42,6 +44,8 @@ void ACIA::write(int address, uint8_t value) { if(address&1) { next_transmission_ = value; consider_transmission(); + update_clocking_observer(); + interrupt_request_ = false; } else { if((value&3) == 3) { transmit.reset_writing(); @@ -82,16 +86,22 @@ void ACIA::write(int address, uint8_t value) { void ACIA::run_for(HalfCycles length) { // Transmission. - int transmit_advance = length.as_int(); - if(next_transmission_ != NoTransmission) { - const auto write_data_time_remaining = transmit.write_data_time_remaining(); - if(transmit_advance > write_data_time_remaining) { + const int transmit_advance = length.as_int(); + const auto write_data_time_remaining = transmit.write_data_time_remaining(); + + if(transmit_advance > write_data_time_remaining) { + if(next_transmission_ != NoTransmission) { transmit.flush_writing(); - transmit_advance -= write_data_time_remaining; consider_transmission(); + transmit.advance_writer(transmit_advance - write_data_time_remaining); + } else { + transmit.advance_writer(transmit_advance); + update_clocking_observer(); + interrupt_request_ |= transmit_interrupt_enabled_; } + } else { + transmit.advance_writer(transmit_advance); } - transmit.advance_writer(transmit_advance); // Reception. } @@ -129,3 +139,11 @@ void ACIA::consider_transmission() { next_transmission_ = NoTransmission; } } + +ClockingHint::Preference ACIA::preferred_clocking() { + return (transmit.write_data_time_remaining() > 0) ? ClockingHint::Preference::JustInTime : ClockingHint::Preference::None; +} + +bool ACIA::get_interrupt_line() { + return interrupt_request_; +} diff --git a/Components/6850/6850.hpp b/Components/6850/6850.hpp index bb7aec9c2..1b76726a9 100644 --- a/Components/6850/6850.hpp +++ b/Components/6850/6850.hpp @@ -11,12 +11,13 @@ #include #include "../../ClockReceiver/ClockReceiver.hpp" +#include "../../ClockReceiver/ClockingHintSource.hpp" #include "../SerialPort/SerialPort.hpp" namespace Motorola { namespace ACIA { -class ACIA { +class ACIA: public ClockingHint::Source { public: ACIA(); @@ -40,6 +41,8 @@ class ACIA { void run_for(HalfCycles); + bool get_interrupt_line(); + // Input lines. Serial::Line receive; Serial::Line clear_to_send; @@ -62,6 +65,10 @@ class ACIA { bool receive_interrupt_enabled_ = false; bool transmit_interrupt_enabled_ = false; + + bool interrupt_request_ = false; + + ClockingHint::Preference preferred_clocking() final; }; }