mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-27 00:30:26 +00:00
The keyboard now responds to a reset on its serial line.
This commit is contained in:
parent
75c3e2dacd
commit
83d73fb088
@ -15,6 +15,8 @@ void Line::set_writer_clock_rate(int clock_rate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Line::advance_writer(int cycles) {
|
void Line::advance_writer(int cycles) {
|
||||||
|
if(!cycles) return;
|
||||||
|
|
||||||
remaining_delays_ = std::max(remaining_delays_ - cycles, 0);
|
remaining_delays_ = std::max(remaining_delays_ - cycles, 0);
|
||||||
if(events_.empty()) {
|
if(events_.empty()) {
|
||||||
write_cycles_since_delegate_call_ += cycles;
|
write_cycles_since_delegate_call_ += cycles;
|
||||||
|
@ -36,7 +36,8 @@ const int CLOCK_RATE = 8000000;
|
|||||||
keyboard input and output and mouse handling.
|
keyboard input and output and mouse handling.
|
||||||
*/
|
*/
|
||||||
class IntelligentKeyboard:
|
class IntelligentKeyboard:
|
||||||
public Serial::Line::ReadDelegate {
|
public Serial::Line::ReadDelegate,
|
||||||
|
public ClockingHint::Source {
|
||||||
public:
|
public:
|
||||||
IntelligentKeyboard(Serial::Line &input, Serial::Line &output) : output_line_(output) {
|
IntelligentKeyboard(Serial::Line &input, Serial::Line &output) : output_line_(output) {
|
||||||
input.set_read_delegate(this, Storage::Time(2, 15625));
|
input.set_read_delegate(this, Storage::Time(2, 15625));
|
||||||
@ -54,6 +55,14 @@ class IntelligentKeyboard:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClockingHint::Preference preferred_clocking() final {
|
||||||
|
return output_line_.transmission_data_time_remaining() ? ClockingHint::Preference::RealTime : ClockingHint::Preference::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_for(HalfCycles duration) {
|
||||||
|
output_line_.advance_writer(duration.as_int());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MARK: - Serial line state.
|
// MARK: - Serial line state.
|
||||||
int bit_count_ = 0;
|
int bit_count_ = 0;
|
||||||
@ -63,6 +72,7 @@ class IntelligentKeyboard:
|
|||||||
void output_byte(uint8_t value) {
|
void output_byte(uint8_t value) {
|
||||||
// Wrap the value in a start and stop bit, and send it on its way.
|
// Wrap the value in a start and stop bit, and send it on its way.
|
||||||
output_line_.write(2, 10, 0x200 | (value << 1));
|
output_line_.write(2, 10, 0x200 | (value << 1));
|
||||||
|
update_clocking_observer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Command dispatch.
|
// MARK: - Command dispatch.
|
||||||
@ -242,6 +252,7 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
midi_acia_->set_clocking_hint_observer(this);
|
midi_acia_->set_clocking_hint_observer(this);
|
||||||
keyboard_acia_->set_clocking_hint_observer(this);
|
keyboard_acia_->set_clocking_hint_observer(this);
|
||||||
|
ikbd_.set_clocking_hint_observer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ConcreteMachine() {
|
~ConcreteMachine() {
|
||||||
@ -528,6 +539,11 @@ class ConcreteMachine:
|
|||||||
midi_acia_.flush();
|
midi_acia_.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(keyboard_needs_clock_) {
|
||||||
|
cycles_since_ikbd_update_ += length;
|
||||||
|
ikbd_.run_for(cycles_since_ikbd_update_.divide(HalfCycles(512)));
|
||||||
|
}
|
||||||
|
|
||||||
while(length >= cycles_until_video_event_) {
|
while(length >= cycles_until_video_event_) {
|
||||||
length -= cycles_until_video_event_;
|
length -= cycles_until_video_event_;
|
||||||
video_ += cycles_until_video_event_;
|
video_ += cycles_until_video_event_;
|
||||||
@ -557,6 +573,7 @@ class ConcreteMachine:
|
|||||||
Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
|
Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
|
||||||
HalfCycles cycles_since_audio_update_;
|
HalfCycles cycles_since_audio_update_;
|
||||||
|
|
||||||
|
HalfCycles cycles_since_ikbd_update_;
|
||||||
IntelligentKeyboard ikbd_;
|
IntelligentKeyboard ikbd_;
|
||||||
|
|
||||||
std::vector<uint16_t> ram_;
|
std::vector<uint16_t> ram_;
|
||||||
@ -568,12 +585,14 @@ class ConcreteMachine:
|
|||||||
BusDevice memory_map_[256];
|
BusDevice memory_map_[256];
|
||||||
|
|
||||||
bool may_defer_acias_ = true;
|
bool may_defer_acias_ = true;
|
||||||
|
bool keyboard_needs_clock_ = false;
|
||||||
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final {
|
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final {
|
||||||
// This is being called by one of the components; avoid any time flushing here as that's
|
// This is being called by one of the components; avoid any time flushing here as that's
|
||||||
// already dealt with (and, just to be absolutely sure, to avoid recursive mania).
|
// already dealt with (and, just to be absolutely sure, to avoid recursive mania).
|
||||||
may_defer_acias_ =
|
may_defer_acias_ =
|
||||||
(keyboard_acia_.last_valid()->preferred_clocking() != ClockingHint::Preference::RealTime) &&
|
(keyboard_acia_.last_valid()->preferred_clocking() != ClockingHint::Preference::RealTime) &&
|
||||||
(midi_acia_.last_valid()->preferred_clocking() != ClockingHint::Preference::RealTime);
|
(midi_acia_.last_valid()->preferred_clocking() != ClockingHint::Preference::RealTime);
|
||||||
|
keyboard_needs_clock_ = ikbd_.preferred_clocking() != ClockingHint::Preference::None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user