mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +00:00
Merge pull request #674 from TomHarte/LessACIAState
Reduces redundant ACIA state.
This commit is contained in:
commit
b019c6f8dd
@ -21,26 +21,11 @@ ACIA::ACIA(HalfCycles transmit_clock_rate, HalfCycles receive_clock_rate) :
|
||||
|
||||
uint8_t ACIA::read(int address) {
|
||||
if(address&1) {
|
||||
clear_interrupt_cause(ReceiveNeedsRead);
|
||||
received_data_ |= NoValueMask;
|
||||
update_interrupt_line();
|
||||
return uint8_t(received_data_);
|
||||
} else {
|
||||
return
|
||||
((received_data_ & NoValueMask) ? 0x00 : 0x01) |
|
||||
((next_transmission_ == NoValueMask) ? 0x02 : 0x00) |
|
||||
(data_carrier_detect.read() ? 0x04 : 0x00) |
|
||||
(clear_to_send.read() ? 0x08 : 0x00) |
|
||||
(interrupt_causes_ ? 0x80 : 0x00)
|
||||
;
|
||||
|
||||
// b0: receive data full.
|
||||
// b1: transmit data empty.
|
||||
// b2: DCD.
|
||||
// b3: CTS.
|
||||
// b4: framing error (i.e. no first stop bit where expected).
|
||||
// b5: receiver overran.
|
||||
// b6: parity error.
|
||||
// b7: IRQ state.
|
||||
return get_status();
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +33,7 @@ void ACIA::write(int address, uint8_t value) {
|
||||
if(address&1) {
|
||||
next_transmission_ = value;
|
||||
consider_transmission();
|
||||
clear_interrupt_cause(TransmitNeedsWrite);
|
||||
update_interrupt_line();
|
||||
} else {
|
||||
if((value&3) == 3) {
|
||||
transmit.reset_writing();
|
||||
@ -85,6 +70,8 @@ void ACIA::write(int address, uint8_t value) {
|
||||
}
|
||||
receive.set_read_delegate(this, Storage::Time(divider_ * 2, int(receive_clock_rate_.as_integral())));
|
||||
receive_interrupt_enabled_ = value & 0x80;
|
||||
|
||||
update_interrupt_line();
|
||||
}
|
||||
}
|
||||
update_clocking_observer();
|
||||
@ -132,7 +119,7 @@ ClockingHint::Preference ACIA::preferred_clocking() {
|
||||
}
|
||||
|
||||
bool ACIA::get_interrupt_line() const {
|
||||
return interrupt_causes_;
|
||||
return interrupt_line_;
|
||||
}
|
||||
|
||||
int ACIA::expected_bits() {
|
||||
@ -157,7 +144,7 @@ bool ACIA::serial_line_did_produce_bit(Serial::Line *line, int bit) {
|
||||
if(bits_received_ >= bit_target) {
|
||||
bits_received_ = 0;
|
||||
received_data_ = uint8_t(bits_incoming_ >> (12 - bit_target));
|
||||
if(receive_interrupt_enabled_) add_interrupt_cause(ReceiveNeedsRead);
|
||||
update_interrupt_line();
|
||||
update_clocking_observer();
|
||||
return false;
|
||||
}
|
||||
@ -173,16 +160,51 @@ void ACIA::set_interrupt_delegate(InterruptDelegate *delegate) {
|
||||
interrupt_delegate_ = delegate;
|
||||
}
|
||||
|
||||
void ACIA::add_interrupt_cause(int cause) {
|
||||
const bool is_changing_state = !interrupt_causes_;
|
||||
interrupt_causes_ |= cause;
|
||||
if(interrupt_delegate_ && is_changing_state)
|
||||
void ACIA::update_interrupt_line() {
|
||||
const bool old_line = interrupt_line_;
|
||||
|
||||
/*
|
||||
"Bit 7 of the control register is the rie bit. When the rie bit is high, the rdrf, ndcd,
|
||||
and ovr bits will assert the nirq output. When the rie bit is low, nirq generation is disabled."
|
||||
|
||||
rie = read interrupt enable
|
||||
rdrf = receive data register full (status word bit 0)
|
||||
ndcd = data carrier detect (status word bit 2)
|
||||
over = receiver overrun (status word bit 5)
|
||||
|
||||
"Bit 1 of the status register is the tdre bit. When high, the tdre bit indicates that data has been
|
||||
transferred from the transmitter data register to the output shift register. At this point, the a6850
|
||||
is ready to accept a new transmit data byte. However, if the ncts signal is high, the tdre bit remains
|
||||
low regardless of the status of the transmitter data register. Also, if transmit interrupt is enabled,
|
||||
the nirq output is asserted."
|
||||
|
||||
tdre = transmitter data register empty
|
||||
ncts = clear to send
|
||||
*/
|
||||
const auto status = get_status();
|
||||
interrupt_line_ =
|
||||
(receive_interrupt_enabled_ && (status & 0x25)) ||
|
||||
(transmit_interrupt_enabled_ && (status & 0x02));
|
||||
|
||||
if(interrupt_delegate_ && old_line != interrupt_line_)
|
||||
interrupt_delegate_->acia6850_did_change_interrupt_status(this);
|
||||
}
|
||||
|
||||
void ACIA::clear_interrupt_cause(int cause) {
|
||||
const bool was_set = interrupt_causes_;
|
||||
interrupt_causes_ &= ~cause;
|
||||
if(interrupt_delegate_ && was_set && !interrupt_causes_)
|
||||
interrupt_delegate_->acia6850_did_change_interrupt_status(this);
|
||||
uint8_t ACIA::get_status() {
|
||||
return
|
||||
((received_data_ & NoValueMask) ? 0x00 : 0x01) |
|
||||
((next_transmission_ == NoValueMask) ? 0x02 : 0x00) |
|
||||
// (data_carrier_detect.read() ? 0x04 : 0x00) |
|
||||
// (clear_to_send.read() ? 0x08 : 0x00) |
|
||||
(interrupt_line_ ? 0x80 : 0x00)
|
||||
;
|
||||
|
||||
// b0: receive data full.
|
||||
// b1: transmit data empty.
|
||||
// b2: DCD.
|
||||
// b3: CTS.
|
||||
// b4: framing error (i.e. no first stop bit where expected).
|
||||
// b5: receiver overran.
|
||||
// b6: parity error.
|
||||
// b7: IRQ state.
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class ACIA: public ClockingHint::Source, private Serial::Line::ReadDelegate {
|
||||
} else {
|
||||
transmit.advance_writer(transmission_cycles);
|
||||
update_clocking_observer();
|
||||
if(transmit_interrupt_enabled_) add_interrupt_cause(TransmitNeedsWrite);
|
||||
update_interrupt_line();
|
||||
}
|
||||
} else {
|
||||
transmit.advance_writer(transmission_cycles);
|
||||
@ -118,15 +118,10 @@ class ACIA: public ClockingHint::Source, private Serial::Line::ReadDelegate {
|
||||
|
||||
bool serial_line_did_produce_bit(Serial::Line *line, int bit) final;
|
||||
|
||||
enum InterruptCause: int {
|
||||
TransmitNeedsWrite = 1 << 0,
|
||||
ReceiveNeedsRead = 1 << 1,
|
||||
StatusNeedsRead = 1 << 2
|
||||
};
|
||||
int interrupt_causes_ = 0;
|
||||
void add_interrupt_cause(int cause);
|
||||
void clear_interrupt_cause(int cause);
|
||||
bool interrupt_line_ = false;
|
||||
void update_interrupt_line();
|
||||
InterruptDelegate *interrupt_delegate_ = nullptr;
|
||||
uint8_t get_status();
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user