diff --git a/InstructionSets/M50740/Executor.cpp b/InstructionSets/M50740/Executor.cpp
index 3e9339bda..f216f38f0 100644
--- a/InstructionSets/M50740/Executor.cpp
+++ b/InstructionSets/M50740/Executor.cpp
@@ -42,7 +42,8 @@ void Executor::set_rom(const std::vector<uint8_t> &rom) {
 }
 
 void Executor::run_for(Cycles cycles) {
-	// The incoming clock is divided by four.
+	// The incoming clock is divided by four; the local cycles_ count
+	// ensures that fractional parts are kept track of.
 	cycles_ += cycles;
 	CachingExecutor::run_for(cycles_.divide(Cycles(4)).as<int>());
 }
@@ -54,8 +55,13 @@ void Executor::reset() {
 
 uint8_t Executor::read(uint16_t address) {
 	address &= 0x1fff;
+	if(address < 0x60) {
+		return memory_[address];
+	}
+
+	port_handler_.run_ports_for(cycles_since_port_handler_.flush<Cycles>());
 	switch(address) {
-		default: return memory_[address];
+		default: return 0xff;
 
 		// TODO: external IO ports.
 
@@ -89,6 +95,8 @@ void Executor::write(uint16_t address, uint8_t value) {
 		return;
 	}
 
+	port_handler_.run_ports_for(cycles_since_port_handler_.flush<Cycles>());
+
 	// TODO: all external IO ports.
 	switch(address) {
 		default: break;
@@ -706,3 +714,8 @@ template <Operation operation> void Executor::perform(uint8_t *operand [[maybe_u
 	}
 #undef set_nz
 }
+
+inline void Executor::subtract_duration(int duration) {
+	cycles_since_port_handler_ += Cycles(duration);
+	CachingExecutor::subtract_duration(duration);
+}
diff --git a/InstructionSets/M50740/Executor.hpp b/InstructionSets/M50740/Executor.hpp
index a15fa73de..e1b47461b 100644
--- a/InstructionSets/M50740/Executor.hpp
+++ b/InstructionSets/M50740/Executor.hpp
@@ -25,6 +25,7 @@ class Executor;
 using CachingExecutor = CachingExecutor<Executor, 0x1fff, 255, Instruction, false>;
 
 struct PortHandler {
+	virtual void run_ports_for(Cycles) = 0;
 	virtual void set_port_output(int port, uint8_t value) = 0;
 	virtual uint8_t get_port_input(int port) = 0;
 };
@@ -143,8 +144,12 @@ class Executor: public CachingExecutor {
 		inline uint8_t flags();
 		template<bool is_brk> inline void perform_interrupt();
 
+		// MARK: - Execution time
+
 		Cycles cycles_;
+		Cycles cycles_since_port_handler_;
 		PortHandler &port_handler_;
+		inline void subtract_duration(int duration);
 };
 
 }
diff --git a/Machines/Apple/AppleIIgs/ADB.cpp b/Machines/Apple/AppleIIgs/ADB.cpp
index 0247211ba..619107b65 100644
--- a/Machines/Apple/AppleIIgs/ADB.cpp
+++ b/Machines/Apple/AppleIIgs/ADB.cpp
@@ -240,13 +240,36 @@ void GLU::set_port_output(int port, uint8_t value) {
 //			printf("IIe keyboard reset line: %d\n", (value >> 6)&1);
 //			printf("IIgs reset line: %d\n", (value >> 5)&1);
 //			printf("GLU strobe: %d\n", (value >> 4)&1);
-			printf("Select GLU register: %d [%02x]\n", value & 0xf, value);
+//			printf("Select GLU register: %d [%02x]\n", value & 0xf, value);
 			register_address_ = value & 0xf;
 		break;
-		case 3:
+		case 3: {
 //			printf("IIe KWS: %d\n", (value >> 6)&3);
-			printf("ADB data line output: %d\n", (value >> 3)&1);
-		break;
+//			printf("ADB data line output: %d\n", (value >> 3)&1);
+
+			const bool new_adb_level = value & 0x08;
+			if(new_adb_level != adb_level_) {
+				if(!new_adb_level) {
+					// Transition to low.
+					constexpr float clock_rate = 894886.25;
+					const float seconds = float(total_period_.as<int>()) / clock_rate;
+
+					// Check for a valid bit length — 70 to 130 microseconds.
+					// (Plus a little).
+					if(seconds >= 0.000'56 && seconds <= 0.001'04) {
+						printf("Attention\n");
+					} else if(seconds >= 0.000'06 && seconds <= 0.000'14) {
+						printf("bit: %d\n", (low_period_.as<int>() * 2) < total_period_.as<int>());
+//						printf("tested: %0.2f\n", float(low_period_.as<int>()) / float(total_period_.as<int>()));
+					} else {
+						printf("Rejected %d microseconds\n", int(seconds * 1'000'000.0f));
+					}
+
+					total_period_ = low_period_ = Cycles(0);
+				}
+				adb_level_ = new_adb_level;
+			}
+		} break;
 
 		default: assert(false);
 	}
@@ -261,7 +284,7 @@ uint8_t GLU::get_port_input(int port) {
 //			printf("IIe keyboard read\n");
 		return 0x06;
 		case 2:
-			printf("ADB data line input, etc\n");
+//			printf("ADB data line input, etc\n");
 		return ports_[2];
 		case 3:
 //			printf("ADB data line output, etc\n");
@@ -271,3 +294,10 @@ uint8_t GLU::get_port_input(int port) {
 	}
 	return 0xff;
 }
+
+void GLU::run_ports_for(Cycles cycles) {
+	total_period_ += cycles;
+	if(!adb_level_) {
+		low_period_ += cycles;
+	}
+}
diff --git a/Machines/Apple/AppleIIgs/ADB.hpp b/Machines/Apple/AppleIIgs/ADB.hpp
index 4239bdb75..5dc5552d4 100644
--- a/Machines/Apple/AppleIIgs/ADB.hpp
+++ b/Machines/Apple/AppleIIgs/ADB.hpp
@@ -62,12 +62,17 @@ class GLU: public InstructionSet::M50740::PortHandler {
 
 		InstructionSet::M50740::Executor executor_;
 
+		void run_ports_for(Cycles) override;
 		void set_port_output(int port, uint8_t value) override;
 		uint8_t get_port_input(int port) override;
 
 		uint8_t registers_[16];
 		uint8_t register_address_;
 		uint8_t ports_[4];
+
+		// TODO: this should be per peripheral. But I'm putting it here for now as an exploratory step.
+		bool adb_level_ = true;
+		Cycles low_period_, total_period_;
 };
 
 }
diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp
index 47156da16..69d62a635 100644
--- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp
+++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp
@@ -186,6 +186,7 @@ class ConcreteMachine:
 		void flush() {
 			video_.flush();
 			iwm_.flush();
+			adb_glu_.flush();
 
 			AudioUpdater updater(this);
 			audio_queue_.perform();
@@ -916,7 +917,7 @@ class ConcreteMachine:
 
 		Apple::Clock::ParallelClock clock_;
 		JustInTimeActor<Apple::IIgs::Video::Video, 1, 2, Cycles> video_;	// i.e. run video at 7Mhz.
-		JustInTimeActor<Apple::IIgs::ADB::GLU, 1, 4, Cycles> adb_glu_;
+		JustInTimeActor<Apple::IIgs::ADB::GLU, 1, 4, Cycles> adb_glu_;		// i.e. 3,579,545Mhz.
  		Zilog::SCC::z8530 scc_;
  		JustInTimeActor<Apple::IWM, 1, 2, Cycles> iwm_;
  		Cycles cycles_since_clock_tick_;