mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Corrects reactive-device transmission logic.
Albeit that I'm still not properly responding to register 3 stuff, so the ADB bus needn't believe anything is out there. Also, without VSYNC being piped to the microcontroller it may well just not be polling anyway.
This commit is contained in:
parent
17e9305282
commit
a51d143c35
@ -72,12 +72,12 @@ void Bus::set_device_output(size_t device_id, bool output) {
|
||||
void Bus::shift(unsigned int value) {
|
||||
shift_register_ = (shift_register_ << 1) | value;
|
||||
|
||||
// Trigger a byte whenever a start bit hits bit 9.
|
||||
if(shift_register_ & 0x200) {
|
||||
// Trigger a byte whenever a start bit hits bit 8.
|
||||
if(shift_register_ & 0x100) {
|
||||
for(auto device: devices_) {
|
||||
device->adb_bus_did_observe_event(Event::Byte, uint8_t(shift_register_ >> 1));
|
||||
device->adb_bus_did_observe_event(Event::Byte, uint8_t(shift_register_));
|
||||
}
|
||||
shift_register_ = 0;
|
||||
shift_register_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +85,9 @@ bool Bus::get_state() const {
|
||||
const auto microseconds = time_since_get_state_.as<double>() * half_cycles_to_microseconds_;
|
||||
time_since_get_state_ = HalfCycles(0);
|
||||
|
||||
const bool current_level = bus_state_.all();
|
||||
for(auto device: devices_) {
|
||||
device->advance_state(microseconds);
|
||||
device->advance_state(microseconds, current_level);
|
||||
}
|
||||
return bus_state_.all();
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class Bus {
|
||||
/// 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;
|
||||
virtual void advance_state(double microseconds, bool current_level) = 0;
|
||||
};
|
||||
/*!
|
||||
Adds a device.
|
||||
|
@ -18,6 +18,11 @@ void Keyboard::perform_command(const Command &command) {
|
||||
case 0:
|
||||
// Post up to two key events, or nothing if there are
|
||||
// no events pending.
|
||||
//
|
||||
// Events are:
|
||||
//
|
||||
// b7 = 0 for down 1, for up;
|
||||
// b6–b0: key code (mostly 7-bit ASCII)
|
||||
// post_response({0x00, 0x00});
|
||||
break;
|
||||
|
||||
|
@ -21,42 +21,53 @@ ReactiveDevice::ReactiveDevice(Apple::ADB::Bus &bus, uint8_t adb_device_id) :
|
||||
void ReactiveDevice::post_response(const std::vector<uint8_t> &&response) {
|
||||
response_ = std::move(response);
|
||||
microseconds_at_bit_ = 0.0;
|
||||
bit_offset_ = -1;
|
||||
bit_offset_ = -2;
|
||||
}
|
||||
|
||||
void ReactiveDevice::advance_state(double microseconds) {
|
||||
void ReactiveDevice::advance_state(double microseconds, bool current_level) {
|
||||
// Do nothing if not in the process of posting a response.
|
||||
if(response_.empty()) return;
|
||||
|
||||
// Otherwise advance time appropriately.
|
||||
// Wait for the bus to be clear if transmission has not yet begun.
|
||||
if(!current_level && bit_offset_ == -2) return;
|
||||
|
||||
// Advance time.
|
||||
microseconds_at_bit_ += microseconds;
|
||||
|
||||
// Bit '-1' is the sync signal.
|
||||
if(bit_offset_ == -1) {
|
||||
bus_.set_device_output(device_id_, false);
|
||||
if(microseconds_at_bit_ < 300) {
|
||||
// If this is the start of the packet, wait an appropriate stop-to-start time.
|
||||
if(bit_offset_ == -2) {
|
||||
if(microseconds_at_bit_ < 250.0) {
|
||||
return;
|
||||
}
|
||||
microseconds_at_bit_ -= 300;
|
||||
microseconds_at_bit_ -= 250.0;
|
||||
++bit_offset_;
|
||||
}
|
||||
|
||||
// Advance the implied number of bits.
|
||||
const int step = int(microseconds_at_bit_ / 100);
|
||||
const int step = int(microseconds_at_bit_ / 100.0);
|
||||
bit_offset_ += step;
|
||||
microseconds_at_bit_ -= double(step * 100.0);
|
||||
|
||||
// Check for end-of-transmission.
|
||||
if(bit_offset_ >= int(response_.size() * 10)) {
|
||||
const int response_bit_length = int(response_.size() * 8);
|
||||
if(bit_offset_ >= 1 + response_bit_length) {
|
||||
bus_.set_device_output(device_id_, true);
|
||||
response_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise pick an output level.
|
||||
const int byte = bit_offset_ / 10;
|
||||
const int bit = ((0x200 | (int(response_[size_t(byte)]) << 1)) >> (bit_offset_ % 10)) & 1;
|
||||
// Otherwise pick the bit to output: it'll either be the start bit of 1,
|
||||
// from the provided data, or a stop bit of 0.
|
||||
int bit = 0;
|
||||
if(bit_offset_ < 0) {
|
||||
bit = 1;
|
||||
} else if(bit_offset_ < response_bit_length) {
|
||||
const int byte = bit_offset_ >> 3;
|
||||
const int packet = int(response_[size_t(byte)]);
|
||||
bit = (packet >> (7 - (bit_offset_ & 7))) & 1;
|
||||
}
|
||||
|
||||
// Convert that into a level.
|
||||
constexpr double low_periods[] = {66, 33};
|
||||
bus_.set_device_output(device_id_, microseconds_at_bit_ > low_periods[bit]);
|
||||
}
|
||||
@ -79,3 +90,7 @@ void ReactiveDevice::adb_bus_did_observe_event(Bus::Event event, uint8_t value)
|
||||
next_is_command_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ReactiveDevice::post_service_request() {
|
||||
// TODO.
|
||||
}
|
||||
|
@ -22,10 +22,11 @@ class ReactiveDevice: public Bus::Device {
|
||||
ReactiveDevice(Bus &bus, uint8_t adb_device_id);
|
||||
|
||||
void post_response(const std::vector<uint8_t> &&response);
|
||||
void post_service_request();
|
||||
virtual void perform_command(const Command &command) = 0;
|
||||
|
||||
private:
|
||||
void advance_state(double microseconds) override;
|
||||
void advance_state(double microseconds, bool current_level) override;
|
||||
void adb_bus_did_observe_event(Bus::Event event, uint8_t value) override;
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user