1
0
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:
Thomas Harte 2021-02-14 18:54:22 -05:00
parent 17e9305282
commit a51d143c35
5 changed files with 42 additions and 20 deletions

View File

@ -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();
}

View File

@ -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.

View File

@ -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;
// b6b0: key code (mostly 7-bit ASCII)
// post_response({0x00, 0x00});
break;

View File

@ -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.
}

View File

@ -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: