// // Bus.cpp // Clock Signal // // Created by Thomas Harte on 10/02/2021. // Copyright © 2021 Thomas Harte. All rights reserved. // #include "Bus.hpp" using namespace Apple::ADB; Bus::Bus(HalfCycles clock_speed) : half_cycles_to_microseconds_(1'000'000.0 / clock_speed.as()) {} void Bus::run_for(HalfCycles duration) { time_in_state_ += duration; time_since_get_state_ += duration; } void Bus::set_device_output(size_t device_id, bool output) { // Modify the all-devices bus state. bus_state_[device_id] = output; // React to signal edges only; don't use get_state here to avoid // endless recursion should any reactive devices set new output // during the various calls made below. const bool data_level = bus_state_.all(); if(data_level_ != data_level) { data_level_ = data_level; if(data_level) { // This was a transition to high; classify what just happened according to // the duration of the low period. const double low_microseconds = time_in_state_.as() * half_cycles_to_microseconds_; // Low periods: // (partly as adapted from the AN591 data sheet; otherwise from the IIgs reference manual) // // > 1040 µs reset // 560–1040 µs attention // < 50 µs 1 // 50–72 µs 0 // 300 µs service request if(low_microseconds > 1040.0) { for(auto device: devices_) { device->adb_bus_did_observe_event(Event::Reset); } } else if(low_microseconds >= 560.0) { for(auto device: devices_) { device->adb_bus_did_observe_event(Event::Attention); } shift_register_ = 1; start_target_ = 9; // Consume the stop bit before posting the next byte. phase_ = Phase::AttentionCapture; } else if(low_microseconds < 50.0) { shift(1); } else if(low_microseconds < 72.0) { shift(0); } else if(low_microseconds >= 291.0 && low_microseconds <= 309.0) { for(auto device: devices_) { device->adb_bus_did_observe_event(Event::ServiceRequest); } } else { for(auto device: devices_) { device->adb_bus_did_observe_event(Event::Unrecognised); } } } time_in_state_ = HalfCycles(0); } } void Bus::shift(unsigned int value) { shift_register_ = (shift_register_ << 1) | value; // Trigger a byte whenever either: // * a 'start bit' hits bit 8; or // * if this was a command byte, wait for the stop bit (i.e. the start bit hits 9). if(shift_register_ & (1 << start_target_)) { for(auto device: devices_) { device->adb_bus_did_observe_event(Event::Byte, uint8_t(shift_register_ >> (start_target_ - 8))); } // Expect a real start bit only if moving from attention capture to packet // capture. Otherwise adopt an implied start bit. shift_register_ = phase_ == Phase::PacketCapture; start_target_ = 8; phase_ = Phase::PacketCapture; } } bool Bus::get_state() const { const auto microseconds = time_since_get_state_.as() * 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, current_level); } return bus_state_.all(); } size_t Bus::add_device() { 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(); }