mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Attempts to implement transmission interrupts and ClockingHint::Source.
This commit is contained in:
parent
4e5b440145
commit
a7ed357569
@ -18,12 +18,14 @@ ACIA::ACIA() {}
|
|||||||
uint8_t ACIA::read(int address) {
|
uint8_t ACIA::read(int address) {
|
||||||
if(address&1) {
|
if(address&1) {
|
||||||
LOG("Read from receive register");
|
LOG("Read from receive register");
|
||||||
|
interrupt_request_ = false;
|
||||||
} else {
|
} else {
|
||||||
LOG("Read status");
|
LOG("Read status");
|
||||||
return
|
return
|
||||||
((next_transmission_ == NoTransmission) ? 0x02 : 0x00) |
|
((next_transmission_ == NoTransmission) ? 0x02 : 0x00) |
|
||||||
(data_carrier_detect.read() ? 0x04 : 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.
|
// b0: receive data full.
|
||||||
@ -42,6 +44,8 @@ void ACIA::write(int address, uint8_t value) {
|
|||||||
if(address&1) {
|
if(address&1) {
|
||||||
next_transmission_ = value;
|
next_transmission_ = value;
|
||||||
consider_transmission();
|
consider_transmission();
|
||||||
|
update_clocking_observer();
|
||||||
|
interrupt_request_ = false;
|
||||||
} else {
|
} else {
|
||||||
if((value&3) == 3) {
|
if((value&3) == 3) {
|
||||||
transmit.reset_writing();
|
transmit.reset_writing();
|
||||||
@ -82,16 +86,22 @@ void ACIA::write(int address, uint8_t value) {
|
|||||||
|
|
||||||
void ACIA::run_for(HalfCycles length) {
|
void ACIA::run_for(HalfCycles length) {
|
||||||
// Transmission.
|
// Transmission.
|
||||||
int transmit_advance = length.as_int();
|
const int transmit_advance = length.as_int();
|
||||||
if(next_transmission_ != NoTransmission) {
|
const auto write_data_time_remaining = transmit.write_data_time_remaining();
|
||||||
const auto write_data_time_remaining = transmit.write_data_time_remaining();
|
|
||||||
if(transmit_advance > write_data_time_remaining) {
|
if(transmit_advance > write_data_time_remaining) {
|
||||||
|
if(next_transmission_ != NoTransmission) {
|
||||||
transmit.flush_writing();
|
transmit.flush_writing();
|
||||||
transmit_advance -= write_data_time_remaining;
|
|
||||||
consider_transmission();
|
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.
|
// Reception.
|
||||||
}
|
}
|
||||||
@ -129,3 +139,11 @@ void ACIA::consider_transmission() {
|
|||||||
next_transmission_ = NoTransmission;
|
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_;
|
||||||
|
}
|
||||||
|
@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||||
|
#include "../../ClockReceiver/ClockingHintSource.hpp"
|
||||||
#include "../SerialPort/SerialPort.hpp"
|
#include "../SerialPort/SerialPort.hpp"
|
||||||
|
|
||||||
namespace Motorola {
|
namespace Motorola {
|
||||||
namespace ACIA {
|
namespace ACIA {
|
||||||
|
|
||||||
class ACIA {
|
class ACIA: public ClockingHint::Source {
|
||||||
public:
|
public:
|
||||||
ACIA();
|
ACIA();
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ class ACIA {
|
|||||||
|
|
||||||
void run_for(HalfCycles);
|
void run_for(HalfCycles);
|
||||||
|
|
||||||
|
bool get_interrupt_line();
|
||||||
|
|
||||||
// Input lines.
|
// Input lines.
|
||||||
Serial::Line receive;
|
Serial::Line receive;
|
||||||
Serial::Line clear_to_send;
|
Serial::Line clear_to_send;
|
||||||
@ -62,6 +65,10 @@ class ACIA {
|
|||||||
|
|
||||||
bool receive_interrupt_enabled_ = false;
|
bool receive_interrupt_enabled_ = false;
|
||||||
bool transmit_interrupt_enabled_ = false;
|
bool transmit_interrupt_enabled_ = false;
|
||||||
|
|
||||||
|
bool interrupt_request_ = false;
|
||||||
|
|
||||||
|
ClockingHint::Preference preferred_clocking() final;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user