1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-09 15:39:08 +00:00

Drives can now deliver activity events.

This commit is contained in:
Thomas Harte 2018-05-10 21:54:10 -04:00
parent 85e1610627
commit ef19a03efc
12 changed files with 77 additions and 32 deletions

View File

@ -1,16 +1,18 @@
//
// Header.h
// ActivityObserver.h
// Clock Signal
//
// Created by Thomas Harte on 07/05/2018.
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Header_h
#define Header_h
#ifndef ActivityObserver_h
#define ActivityObserver_h
#include <string>
namespace Activity {
/*!
Provides a purely virtual base class for anybody that wants to receive notifications of
'activity' any feedback from an emulated system which a user could perceive other than
@ -19,7 +21,7 @@
So: status LEDs, drive activity, etc. A receiver may choose to make appropriate noises
and/or to show or unshow status indicators.
*/
class ActivityObserver {
class Observer {
public:
/// Announces to the receiver that there is an LED of name @c name.
virtual void register_led(const std::string &name) = 0;
@ -44,4 +46,6 @@ class ActivityObserver {
};
#endif /* Header_h */
}
#endif /* ActivityObserver_h */

View File

@ -9,13 +9,13 @@
#ifndef ActivitySource_h
#define ActivitySource_h
#include "../ActivityObserver/ActivityObserver.hpp"
#include "Observer.hpp"
namespace ActivitySource {
namespace Activity {
class Machine {
class Source {
public:
virtual void set_activity_observer(ActivityObserver *receiver) = 0;
virtual void set_activity_observer(Observer *observer) = 0;
};
}

View File

@ -22,7 +22,7 @@ MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machin
crt_machine_.set_delegate(this);
}
ActivitySource::Machine *MultiMachine::activity_source() {
Activity::Source *MultiMachine::activity_source() {
return nullptr; // TODO
}

View File

@ -50,7 +50,7 @@ class MultiMachine: public ::Machine::DynamicMachine, public MultiCRTMachine::De
static bool would_collapse(const std::vector<std::unique_ptr<DynamicMachine>> &machines);
MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines);
ActivitySource::Machine *activity_source() override;
Activity::Source *activity_source() override;
ConfigurationTarget::Machine *configuration_target() override;
CRTMachine::Machine *crt_machine() override;
JoystickMachine::Machine *joystick_machine() override;

View File

@ -10,7 +10,7 @@
#define DynamicMachine_h
#include "../Configurable/Configurable.hpp"
#include "ActivitySource.hpp"
#include "../Activity/Source.hpp"
#include "ConfigurationTarget.hpp"
#include "CRTMachine.hpp"
#include "JoystickMachine.hpp"
@ -26,7 +26,7 @@ namespace Machine {
struct DynamicMachine {
virtual ~DynamicMachine() {}
virtual ActivitySource::Machine *activity_source() = 0;
virtual Activity::Source *activity_source() = 0;
virtual ConfigurationTarget::Machine *configuration_target() = 0;
virtual CRTMachine::Machine *crt_machine() = 0;
virtual JoystickMachine::Machine *joystick_machine() = 0;

View File

@ -8,7 +8,7 @@
#include "Electron.hpp"
#include "../ActivitySource.hpp"
#include "../../Activity/Source.hpp"
#include "../ConfigurationTarget.hpp"
#include "../CRTMachine.hpp"
#include "../KeyboardMachine.hpp"
@ -47,7 +47,7 @@ class ConcreteMachine:
public CPU::MOS6502::BusHandler,
public Tape::Delegate,
public Utility::TypeRecipient,
public ActivitySource::Machine {
public Activity::Source {
public:
ConcreteMachine() :
m6502_(*this),
@ -480,7 +480,7 @@ class ConcreteMachine:
return selection_set;
}
void set_activity_observer(ActivityObserver *observer) override {
void set_activity_observer(Activity::Observer *observer) override {
activity_observer_ = observer;
if(activity_observer_) {
activity_observer_->register_led(caps_led);
@ -578,7 +578,7 @@ class ConcreteMachine:
// MARK: - Caps Lock status and the activity observer.
const std::string caps_led = "CAPS";
bool caps_led_state_ = false;
ActivityObserver *activity_observer_ = nullptr;
Activity::Observer *activity_observer_ = nullptr;
};
}

View File

@ -53,3 +53,8 @@ void Plus3::set_motor_on(bool on) {
// writing state, so plenty of work to do in general here.
get_drive().set_motor_on(on);
}
void Plus3::set_activity_observer(Activity::Observer *observer) {
drives_[0]->set_activity_observer(observer, "Drive 1", true);
drives_[1]->set_activity_observer(observer, "Drive 2", true);
}

View File

@ -10,6 +10,7 @@
#define Plus3_hpp
#include "../../Components/1770/1770.hpp"
#include "../../Activity/Observer.hpp"
namespace Electron {
@ -19,6 +20,7 @@ class Plus3 : public WD::WD1770 {
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive);
void set_control_register(uint8_t control);
void set_activity_observer(Activity::Observer *observer);
private:
void set_control_register(uint8_t control, uint8_t changes);

View File

@ -25,8 +25,8 @@ template<typename T> class TypedDynamicMachine: public ::Machine::DynamicMachine
return *this;
}
ActivitySource::Machine *activity_source() override {
return get<ActivitySource::Machine>();
Activity::Source *activity_source() override {
return get<Activity::Source>();
}
ConfigurationTarget::Machine *configuration_target() override {

View File

@ -697,8 +697,6 @@
4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MachineForTarget.cpp; sourceTree = "<group>"; };
4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MachineForTarget.hpp; sourceTree = "<group>"; };
4B055AF01FAE9C080060FFFF /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
4B055C1E20A113B00014E5AB /* ActivityObserver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ActivityObserver.hpp; sourceTree = "<group>"; };
4B055C1F20A1166A0014E5AB /* ActivitySource.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ActivitySource.hpp; sourceTree = "<group>"; };
4B0783591FC11D10001D12BB /* Configurable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Configurable.cpp; sourceTree = "<group>"; };
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = "<group>"; };
4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = "<group>"; };
@ -865,6 +863,8 @@
4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBuilder.cpp; sourceTree = "<group>"; };
4B5073061DDD3B9400C48FBD /* ArrayBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ArrayBuilder.hpp; sourceTree = "<group>"; };
4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ArrayBuilderTests.mm; sourceTree = "<group>"; };
4B51F70920A521D700AFA2C1 /* Source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Source.hpp; sourceTree = "<group>"; };
4B51F70A20A521D700AFA2C1 /* Observer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Observer.hpp; sourceTree = "<group>"; };
4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardMachine.cpp; sourceTree = "<group>"; };
4B54C0BD1F8D8F450050900F /* Keyboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Keyboard.cpp; path = Oric/Keyboard.cpp; sourceTree = "<group>"; };
4B54C0BE1F8D8F450050900F /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = Keyboard.hpp; path = Oric/Keyboard.hpp; sourceTree = "<group>"; };
@ -1498,15 +1498,6 @@
path = ../SDL;
sourceTree = "<group>";
};
4B055C1D20A113B00014E5AB /* ActivityObserver */ = {
isa = PBXGroup;
children = (
4B055C1E20A113B00014E5AB /* ActivityObserver.hpp */,
);
name = ActivityObserver;
path = ../../ActivityObserver;
sourceTree = "<group>";
};
4B0CCC411C62D0B3001CAC5F /* CRT */ = {
isa = PBXGroup;
children = (
@ -1972,6 +1963,16 @@
path = 1540;
sourceTree = "<group>";
};
4B51F70820A521D700AFA2C1 /* Activity */ = {
isa = PBXGroup;
children = (
4B51F70920A521D700AFA2C1 /* Source.hpp */,
4B51F70A20A521D700AFA2C1 /* Observer.hpp */,
);
name = Activity;
path = ../../Activity;
sourceTree = "<group>";
};
4B55CE551C3B7D360093A61B /* Documents */ = {
isa = PBXGroup;
children = (
@ -2708,7 +2709,7 @@
isa = PBXGroup;
children = (
4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */,
4B055C1D20A113B00014E5AB /* ActivityObserver */,
4B51F70820A521D700AFA2C1 /* Activity */,
4B8944E2201967B4007DE474 /* Analyser */,
4BB73EA01B587A5100552FC2 /* Clock Signal */,
4BB73EB51B587A5100552FC2 /* Clock SignalTests */,
@ -2812,7 +2813,6 @@
isa = PBXGroup;
children = (
4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */,
4B055C1F20A1166A0014E5AB /* ActivitySource.hpp */,
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */,
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */,
4BBB709C2020109C002FE009 /* DynamicMachine.hpp */,

View File

@ -88,6 +88,14 @@ bool Drive::get_is_ready() {
void Drive::set_motor_on(bool motor_is_on) {
motor_is_on_ = motor_is_on;
if(observer_) {
observer_->set_drive_motor_status(drive_name_, motor_is_on_);
if(announce_motor_led_) {
observer_->set_led_status(drive_name_, motor_is_on_);
}
}
if(!motor_is_on) {
ready_index_count_ = 0;
if(disk_) disk_->flush_tracks();
@ -265,3 +273,19 @@ void Drive::end_writing() {
invalidate_track();
}
}
void Drive::set_activity_observer(Activity::Observer *observer, const std::string &name, bool add_motor_led) {
observer_ = observer;
announce_motor_led_ = add_motor_led;
if(observer) {
drive_name_ = name;
observer->register_drive(drive_name_);
observer->set_drive_motor_status(drive_name_, motor_is_on_);
if(add_motor_led) {
observer->register_led(drive_name_);
observer->set_led_status(drive_name_, motor_is_on_);
}
}
}

View File

@ -14,6 +14,7 @@
#include "Track/PCMPatchedTrack.hpp"
#include "../TimedEventLoop.hpp"
#include "../../Activity/Observer.hpp"
#include "../../ClockReceiver/Sleeper.hpp"
#include <memory>
@ -122,6 +123,10 @@ class Drive: public Sleeper, public TimedEventLoop {
// As per Sleeper.
bool is_sleeping();
/// Adds an activity observer; it'll be notified of disk activity.
/// The caller can specify whether to add an LED based on disk motor.
void set_activity_observer(Activity::Observer *observer, const std::string &name, bool add_motor_led);
private:
// Drives contain an entire disk; from that a certain track
// will be currently under the head.
@ -189,6 +194,11 @@ class Drive: public Sleeper, public TimedEventLoop {
void setup_track();
void invalidate_track();
// Activity observer description.
Activity::Observer *observer_ = nullptr;
std::string drive_name_;
bool announce_motor_led_ = false;
};