mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-11 15:30:52 +00:00
Starts to establish the means by which I'll implement ADB devices.
This commit is contained in:
parent
e83b2120ce
commit
adfdfa205f
@ -14,17 +14,12 @@ Bus::Bus(HalfCycles clock_speed) : half_cycles_to_microseconds_(1'000'000.0 / cl
|
|||||||
|
|
||||||
void Bus::run_for(HalfCycles duration) {
|
void Bus::run_for(HalfCycles duration) {
|
||||||
time_in_state_ += duration;
|
time_in_state_ += duration;
|
||||||
|
time_since_get_state_ += duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Bus::add_device() {
|
void Bus::set_device_output(size_t device_id, bool output) {
|
||||||
const size_t id = next_device_id_;
|
|
||||||
++next_device_id_;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bus::set_device_output(size_t device, bool output) {
|
|
||||||
// Modify the all-devices bus state.
|
// Modify the all-devices bus state.
|
||||||
bus_state_[device] = output;
|
bus_state_[device_id] = output;
|
||||||
|
|
||||||
// React to signal edges only.
|
// React to signal edges only.
|
||||||
const bool data_level = get_state();
|
const bool data_level = get_state();
|
||||||
@ -45,12 +40,12 @@ void Bus::set_device_output(size_t device, bool output) {
|
|||||||
// 50–72 µs 0
|
// 50–72 µs 0
|
||||||
// 300 µs service request
|
// 300 µs service request
|
||||||
if(low_microseconds > 1040.0) {
|
if(low_microseconds > 1040.0) {
|
||||||
for(auto observer: observers_) {
|
for(auto device: devices_) {
|
||||||
observer->adb_bus_did_observe_event(this, Event::Reset);
|
device->adb_bus_did_observe_event(Event::Reset);
|
||||||
}
|
}
|
||||||
} else if(low_microseconds >= 560.0) {
|
} else if(low_microseconds >= 560.0) {
|
||||||
for(auto observer: observers_) {
|
for(auto device: devices_) {
|
||||||
observer->adb_bus_did_observe_event(this, Event::Attention);
|
device->adb_bus_did_observe_event(Event::Attention);
|
||||||
}
|
}
|
||||||
shift_register_ = 1;
|
shift_register_ = 1;
|
||||||
} else if(low_microseconds < 50.0) {
|
} else if(low_microseconds < 50.0) {
|
||||||
@ -58,12 +53,12 @@ void Bus::set_device_output(size_t device, bool output) {
|
|||||||
} else if(low_microseconds < 72.0) {
|
} else if(low_microseconds < 72.0) {
|
||||||
shift(0);
|
shift(0);
|
||||||
} else if(low_microseconds >= 291.0 && low_microseconds <= 309.0) {
|
} else if(low_microseconds >= 291.0 && low_microseconds <= 309.0) {
|
||||||
for(auto observer: observers_) {
|
for(auto device: devices_) {
|
||||||
observer->adb_bus_did_observe_event(this, Event::ServiceRequest);
|
device->adb_bus_did_observe_event(Event::ServiceRequest);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(auto observer: observers_) {
|
for(auto device: devices_) {
|
||||||
observer->adb_bus_did_observe_event(this, Event::Unrecognised);
|
device->adb_bus_did_observe_event(Event::Unrecognised);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,17 +72,30 @@ void Bus::shift(unsigned int value) {
|
|||||||
|
|
||||||
// Trigger a byte whenever a start bit hits bit 9.
|
// Trigger a byte whenever a start bit hits bit 9.
|
||||||
if(shift_register_ & 0x200) {
|
if(shift_register_ & 0x200) {
|
||||||
for(auto observer: observers_) {
|
for(auto device: devices_) {
|
||||||
observer->adb_bus_did_observe_event(this, Event::Byte, uint8_t(shift_register_ >> 1));
|
device->adb_bus_did_observe_event(Event::Byte, uint8_t(shift_register_ >> 1));
|
||||||
}
|
}
|
||||||
shift_register_ = 0;
|
shift_register_ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bus::get_state() const {
|
bool Bus::get_state() const {
|
||||||
|
const auto microseconds = time_since_get_state_.as<double>() * half_cycles_to_microseconds_;
|
||||||
|
time_since_get_state_ = HalfCycles(0);
|
||||||
|
|
||||||
|
for(auto device: devices_) {
|
||||||
|
device->advance_state(microseconds);
|
||||||
|
}
|
||||||
return bus_state_.all();
|
return bus_state_.all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::add_observer(Observer *observer) {
|
size_t Bus::add_device() {
|
||||||
observers_.push_back(observer);
|
const size_t id = next_device_id_;
|
||||||
|
++next_device_id_;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Bus::add_device(Device *device) {
|
||||||
|
devices_.push_back(device);
|
||||||
|
return add_device();
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,15 @@ inline Command decode_command(uint8_t code) {
|
|||||||
The ADB bus models the data line of the ADB bus; it allows multiple devices to
|
The ADB bus models the data line of the ADB bus; it allows multiple devices to
|
||||||
post their current data level, or read the current level, and also offers a tokenised
|
post their current data level, or read the current level, and also offers a tokenised
|
||||||
version of all activity on the bus.
|
version of all activity on the bus.
|
||||||
|
|
||||||
|
In implementation terms, two types of device are envisaged:
|
||||||
|
|
||||||
|
* proactive devices, which use @c add_device() and then merely @c set_device_output
|
||||||
|
and @c get_state() as required, according to their own tracking of time; and
|
||||||
|
|
||||||
|
* reactive devices, which use @c add_device(Device*) and then merely react to
|
||||||
|
@c adb_bus_did_observe_event and @c advance_state in order to
|
||||||
|
update @c set_device_output.
|
||||||
*/
|
*/
|
||||||
class Bus {
|
class Bus {
|
||||||
public:
|
public:
|
||||||
@ -77,7 +86,7 @@ class Bus {
|
|||||||
/*!
|
/*!
|
||||||
Sets the current data line output for @c device.
|
Sets the current data line output for @c device.
|
||||||
*/
|
*/
|
||||||
void set_device_output(size_t device, bool output);
|
void set_device_output(size_t device_id, bool output);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@returns The current state of the ADB data line.
|
@returns The current state of the ADB data line.
|
||||||
@ -93,20 +102,28 @@ class Bus {
|
|||||||
Unrecognised
|
Unrecognised
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Observer {
|
struct Device {
|
||||||
/// Reports to an observer that @c event was observed in the activity
|
/// Reports to an observer that @c event was observed in the activity
|
||||||
/// observed on this bus. If this was a byte event, that byte's value is given as @c value.
|
/// observed on this bus. If this was a byte event, that byte's value is given as @c value.
|
||||||
virtual void adb_bus_did_observe_event(Bus *, Event event, uint8_t value = 0xff);
|
virtual void adb_bus_did_observe_event(Event event, uint8_t value = 0xff) = 0;
|
||||||
|
|
||||||
|
/// Requests that the device update itself @c microseconds and, if necessary, post a
|
||||||
|
/// new value ot @c set_device_output. This will be called only when the bus needs
|
||||||
|
/// to reevaluate its current level. It cannot reliably be used to track the timing between
|
||||||
|
/// observed events.
|
||||||
|
virtual void advance_state(double microseconds) = 0;
|
||||||
};
|
};
|
||||||
/*!
|
/*!
|
||||||
Adds an observer.
|
Adds a device.
|
||||||
*/
|
*/
|
||||||
void add_observer(Observer *);
|
size_t add_device(Device *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HalfCycles time_in_state_;
|
HalfCycles time_in_state_;
|
||||||
|
mutable HalfCycles time_since_get_state_;
|
||||||
|
|
||||||
double half_cycles_to_microseconds_ = 1.0;
|
double half_cycles_to_microseconds_ = 1.0;
|
||||||
std::vector<Observer *> observers_;
|
std::vector<Device *> devices_;
|
||||||
unsigned int shift_register_ = 0;
|
unsigned int shift_register_ = 0;
|
||||||
bool data_level_ = true;
|
bool data_level_ = true;
|
||||||
|
|
||||||
|
21
Machines/Apple/ADB/ReactiveDevice.cpp
Normal file
21
Machines/Apple/ADB/ReactiveDevice.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// ReactiveDevice.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 12/02/2021.
|
||||||
|
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ReactiveDevice.hpp"
|
||||||
|
|
||||||
|
using namespace Apple::ADB;
|
||||||
|
|
||||||
|
ReactiveDevice::ReactiveDevice(Apple::ADB::Bus &bus) : device_id_(bus.add_device(this)) {}
|
||||||
|
|
||||||
|
void ReactiveDevice::post_response(const std::vector<uint8_t> &&response) {
|
||||||
|
response_ = std::move(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReactiveDevice::advance_state(double microseconds) {
|
||||||
|
(void)microseconds;
|
||||||
|
}
|
35
Machines/Apple/ADB/ReactiveDevice.hpp
Normal file
35
Machines/Apple/ADB/ReactiveDevice.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// ReactiveDevice.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 12/02/2021.
|
||||||
|
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ReactiveDevice_hpp
|
||||||
|
#define ReactiveDevice_hpp
|
||||||
|
|
||||||
|
#include "Bus.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Apple {
|
||||||
|
namespace ADB {
|
||||||
|
|
||||||
|
class ReactiveDevice: public Bus::Device {
|
||||||
|
protected:
|
||||||
|
ReactiveDevice(Bus &bus);
|
||||||
|
|
||||||
|
void post_response(const std::vector<uint8_t> &&response);
|
||||||
|
void advance_state(double microseconds) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const size_t device_id_;
|
||||||
|
std::vector<uint8_t> response_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ReactiveDevice_hpp */
|
@ -172,6 +172,8 @@
|
|||||||
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFDB01DAEF5FF001A68B8 /* Video.cpp */; };
|
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFDB01DAEF5FF001A68B8 /* Video.cpp */; };
|
||||||
4B2C45421E3C3896002A2389 /* cartridge.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B2C45411E3C3896002A2389 /* cartridge.png */; };
|
4B2C45421E3C3896002A2389 /* cartridge.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B2C45411E3C3896002A2389 /* cartridge.png */; };
|
||||||
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; };
|
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; };
|
||||||
|
4B2E86B725D7490E0024F1E9 /* ReactiveDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E86B525D7490E0024F1E9 /* ReactiveDevice.cpp */; };
|
||||||
|
4B2E86B825D7490E0024F1E9 /* ReactiveDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E86B525D7490E0024F1E9 /* ReactiveDevice.cpp */; };
|
||||||
4B302184208A550100773308 /* DiskII.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B302183208A550100773308 /* DiskII.cpp */; };
|
4B302184208A550100773308 /* DiskII.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B302183208A550100773308 /* DiskII.cpp */; };
|
||||||
4B302185208A550100773308 /* DiskII.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B302183208A550100773308 /* DiskII.cpp */; };
|
4B302185208A550100773308 /* DiskII.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B302183208A550100773308 /* DiskII.cpp */; };
|
||||||
4B30512D1D989E2200B4FED8 /* Drive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512B1D989E2200B4FED8 /* Drive.cpp */; };
|
4B30512D1D989E2200B4FED8 /* Drive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512B1D989E2200B4FED8 /* Drive.cpp */; };
|
||||||
@ -1116,6 +1118,8 @@
|
|||||||
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RegisterSizes.hpp; sourceTree = "<group>"; };
|
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RegisterSizes.hpp; sourceTree = "<group>"; };
|
||||||
4B2E2D9B1C3A070400138695 /* Electron.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Electron.cpp; path = Electron/Electron.cpp; sourceTree = "<group>"; };
|
4B2E2D9B1C3A070400138695 /* Electron.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Electron.cpp; path = Electron/Electron.cpp; sourceTree = "<group>"; };
|
||||||
4B2E2D9C1C3A070400138695 /* Electron.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Electron.hpp; path = Electron/Electron.hpp; sourceTree = "<group>"; };
|
4B2E2D9C1C3A070400138695 /* Electron.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Electron.hpp; path = Electron/Electron.hpp; sourceTree = "<group>"; };
|
||||||
|
4B2E86B525D7490E0024F1E9 /* ReactiveDevice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ReactiveDevice.cpp; sourceTree = "<group>"; };
|
||||||
|
4B2E86B625D7490E0024F1E9 /* ReactiveDevice.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ReactiveDevice.hpp; sourceTree = "<group>"; };
|
||||||
4B302182208A550100773308 /* DiskII.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskII.hpp; sourceTree = "<group>"; };
|
4B302182208A550100773308 /* DiskII.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskII.hpp; sourceTree = "<group>"; };
|
||||||
4B302183208A550100773308 /* DiskII.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskII.cpp; sourceTree = "<group>"; };
|
4B302183208A550100773308 /* DiskII.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskII.cpp; sourceTree = "<group>"; };
|
||||||
4B30512B1D989E2200B4FED8 /* Drive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Drive.cpp; sourceTree = "<group>"; };
|
4B30512B1D989E2200B4FED8 /* Drive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Drive.cpp; sourceTree = "<group>"; };
|
||||||
@ -4189,6 +4193,8 @@
|
|||||||
children = (
|
children = (
|
||||||
4BCE1DEF25D4C3FA00AE7A2B /* Bus.cpp */,
|
4BCE1DEF25D4C3FA00AE7A2B /* Bus.cpp */,
|
||||||
4BCE1DF025D4C3FA00AE7A2B /* Bus.hpp */,
|
4BCE1DF025D4C3FA00AE7A2B /* Bus.hpp */,
|
||||||
|
4B2E86B525D7490E0024F1E9 /* ReactiveDevice.cpp */,
|
||||||
|
4B2E86B625D7490E0024F1E9 /* ReactiveDevice.hpp */,
|
||||||
);
|
);
|
||||||
path = ADB;
|
path = ADB;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -5108,6 +5114,7 @@
|
|||||||
4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */,
|
4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */,
|
||||||
4B25B5F925BD083C00362C84 /* DiskIIDrive.cpp in Sources */,
|
4B25B5F925BD083C00362C84 /* DiskIIDrive.cpp in Sources */,
|
||||||
4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */,
|
4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */,
|
||||||
|
4B2E86B825D7490E0024F1E9 /* ReactiveDevice.cpp in Sources */,
|
||||||
4B74CF822312FA9C00500CE8 /* HFV.cpp in Sources */,
|
4B74CF822312FA9C00500CE8 /* HFV.cpp in Sources */,
|
||||||
4B8318B022D3E531006DB630 /* AppleII.cpp in Sources */,
|
4B8318B022D3E531006DB630 /* AppleII.cpp in Sources */,
|
||||||
4B1B58F7246CC4E8009C171E /* State.cpp in Sources */,
|
4B1B58F7246CC4E8009C171E /* State.cpp in Sources */,
|
||||||
@ -5284,6 +5291,7 @@
|
|||||||
4BE21219253FCE9C00435408 /* AppleIIgs.cpp in Sources */,
|
4BE21219253FCE9C00435408 /* AppleIIgs.cpp in Sources */,
|
||||||
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
|
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
|
||||||
4B0ACC2E23775819008902D0 /* TIA.cpp in Sources */,
|
4B0ACC2E23775819008902D0 /* TIA.cpp in Sources */,
|
||||||
|
4B2E86B725D7490E0024F1E9 /* ReactiveDevice.cpp in Sources */,
|
||||||
4B74CF85231370BC00500CE8 /* MacintoshVolume.cpp in Sources */,
|
4B74CF85231370BC00500CE8 /* MacintoshVolume.cpp in Sources */,
|
||||||
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
|
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
|
||||||
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
|
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user