mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Eliminates unexpected bottleneck created by ACIA.
This commit is contained in:
parent
cc7ff1ec9e
commit
8c736a639a
@ -91,29 +91,6 @@ void ACIA::write(int address, uint8_t value) {
|
||||
update_clocking_observer();
|
||||
}
|
||||
|
||||
void ACIA::run_for(HalfCycles length) {
|
||||
if(transmit.transmission_data_time_remaining() > HalfCycles(0)) {
|
||||
const auto write_data_time_remaining = transmit.write_data_time_remaining();
|
||||
|
||||
// There's at most one further byte available to enqueue, so a single 'if'
|
||||
// rather than a 'while' is correct here. It's the responsibilit of the caller
|
||||
// to ensure run_for lengths are appropriate for longer sequences.
|
||||
if(length >= write_data_time_remaining) {
|
||||
if(next_transmission_ != NoValueMask) {
|
||||
transmit.advance_writer(write_data_time_remaining);
|
||||
consider_transmission();
|
||||
transmit.advance_writer(length - write_data_time_remaining);
|
||||
} else {
|
||||
transmit.advance_writer(length);
|
||||
update_clocking_observer();
|
||||
if(transmit_interrupt_enabled_) add_interrupt_cause(TransmitNeedsWrite);
|
||||
}
|
||||
} else {
|
||||
transmit.advance_writer(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ACIA::consider_transmission() {
|
||||
if(next_transmission_ != NoValueMask && !transmit.write_data_time_remaining()) {
|
||||
// Establish start bit and [7 or 8] data bits.
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../../ClockReceiver/ForceInline.hpp"
|
||||
#include "../../ClockReceiver/ClockingHintSource.hpp"
|
||||
#include "../SerialPort/SerialPort.hpp"
|
||||
|
||||
@ -49,7 +50,28 @@ class ACIA: public ClockingHint::Source, private Serial::Line::ReadDelegate {
|
||||
Advances @c transmission_cycles in time, which should be
|
||||
counted relative to the @c transmit_clock_rate.
|
||||
*/
|
||||
void run_for(HalfCycles transmission_cycles);
|
||||
forceinline void run_for(HalfCycles transmission_cycles) {
|
||||
if(transmit.transmission_data_time_remaining() > HalfCycles(0)) {
|
||||
const auto write_data_time_remaining = transmit.write_data_time_remaining();
|
||||
|
||||
// There's at most one further byte available to enqueue, so a single 'if'
|
||||
// rather than a 'while' is correct here. It's the responsibilit of the caller
|
||||
// to ensure run_for lengths are appropriate for longer sequences.
|
||||
if(transmission_cycles >= write_data_time_remaining) {
|
||||
if(next_transmission_ != NoValueMask) {
|
||||
transmit.advance_writer(write_data_time_remaining);
|
||||
consider_transmission();
|
||||
transmit.advance_writer(transmission_cycles - write_data_time_remaining);
|
||||
} else {
|
||||
transmit.advance_writer(transmission_cycles);
|
||||
update_clocking_observer();
|
||||
if(transmit_interrupt_enabled_) add_interrupt_cause(TransmitNeedsWrite);
|
||||
}
|
||||
} else {
|
||||
transmit.advance_writer(transmission_cycles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool get_interrupt_line() const;
|
||||
|
||||
|
@ -84,14 +84,6 @@ void Line::write(HalfCycles cycles, int count, int levels) {
|
||||
}
|
||||
}
|
||||
|
||||
HalfCycles Line::write_data_time_remaining() {
|
||||
return HalfCycles(remaining_delays_);
|
||||
}
|
||||
|
||||
HalfCycles Line::transmission_data_time_remaining() {
|
||||
return HalfCycles(remaining_delays_ + transmission_extra_);
|
||||
}
|
||||
|
||||
void Line::reset_writing() {
|
||||
remaining_delays_ = 0;
|
||||
events_.clear();
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
#include "../../Storage/Storage.hpp"
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../../ClockReceiver/ForceInline.hpp"
|
||||
|
||||
namespace Serial {
|
||||
|
||||
@ -44,11 +45,15 @@ class Line {
|
||||
void write(HalfCycles cycles, int count, int levels);
|
||||
|
||||
/// @returns the number of cycles until currently enqueued write data is exhausted.
|
||||
HalfCycles write_data_time_remaining();
|
||||
forceinline HalfCycles write_data_time_remaining() const {
|
||||
return HalfCycles(remaining_delays_);
|
||||
}
|
||||
|
||||
/// @returns the number of cycles left until it is guaranteed that a passive reader
|
||||
/// has received all currently-enqueued bits.
|
||||
HalfCycles transmission_data_time_remaining();
|
||||
forceinline HalfCycles transmission_data_time_remaining() const {
|
||||
return HalfCycles(remaining_delays_ + transmission_extra_);
|
||||
}
|
||||
|
||||
/// Eliminates all future write states, leaving the output at whatever it is now.
|
||||
void reset_writing();
|
||||
|
Loading…
x
Reference in New Issue
Block a user