From 9078fc994bee1cebfcfb61c85ddef727a0b1b8ff Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Mar 2024 22:10:52 -0400 Subject: [PATCH] Try to formalise I2C events. --- Components/I2C/I2C.cpp | 49 +++++++++++++++++++++++++++++++----------- Components/I2C/I2C.hpp | 5 +++++ Outputs/Log.hpp | 1 - 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Components/I2C/I2C.cpp b/Components/I2C/I2C.cpp index 05785cc48..f4d8fe6f5 100644 --- a/Components/I2C/I2C.cpp +++ b/Components/I2C/I2C.cpp @@ -37,23 +37,48 @@ bool Bus::clock() { } void Bus::set_clock_data(bool clock_pulled, bool data_pulled) { - const bool prior_clock = clock_; + if(clock_pulled == clock_ && data_pulled == data_) { + return; + } + + auto info = logger.info(); + info.append("C:%d D:%d; ", clock_, data_); + const bool prior_data = data_; clock_ = clock_pulled; data_ = data_pulled; - logger.info().append("C:%d D:%d", clock_, data_); - - // Advance peripheral input from peripheral if clock - // transitions from high to low. - if(peripheral_bits_ && prior_clock && !clock_) { - --peripheral_bits_; - peripheral_response_ <<= 1; + if(clock_) { + info.append("nothing"); + return; } + if(prior_data != data_) { + if(data_) { + info.append("start"); + signal(Event::Start); + } else { + info.append("stop"); + signal(Event::Stop); + } + } else { + --peripheral_bits_; + peripheral_response_ <<= 1; + + if(data_) { + info.append("zero"); + signal(Event::Zero); + } else { + info.append("one"); + signal(Event::One); + } + } +} + +void Bus::signal(Event event) { const auto capture_bit = [&]() { - if(prior_clock && !clock_) { - input_ = uint16_t((input_ << 1) | (data_pulled ? 0 : 1)); + if(event == Event::Zero || event == Event::One) { + input_ = uint16_t((input_ << 1) | (event == Event::Zero ? 0 : 1)); ++input_count_; } }; @@ -68,7 +93,7 @@ void Bus::set_clock_data(bool clock_pulled, bool data_pulled) { // Check for stop condition at any time. // "A LOW-to-HIGH transition of the data line // while the clock is HIGH is defined as the STOP condition". - if(prior_data && !data_ && !clock_) { + if(event == Event::Stop) { logger.info().append("Stopped"); phase_ = Phase::AwaitingStart; } @@ -77,7 +102,7 @@ void Bus::set_clock_data(bool clock_pulled, bool data_pulled) { case Phase::AwaitingStart: // "A HIGH-to-LOW transition of the data line while // the clock is HIGH is defined as the START condition" - if(!prior_data && data_ && !clock_) { + if(event == Event::Start) { phase_ = Phase::CollectingAddress; input_count_ = 0; input_ = 0; diff --git a/Components/I2C/I2C.hpp b/Components/I2C/I2C.hpp index c16134f05..a030f3ede 100644 --- a/Components/I2C/I2C.hpp +++ b/Components/I2C/I2C.hpp @@ -43,6 +43,11 @@ private: uint16_t peripheral_response_ = 0xffff; int peripheral_bits_ = 0; + enum class Event { + Zero, One, Start, Stop, + }; + void signal(Event); + enum class Phase { AwaitingStart, CollectingAddress, diff --git a/Outputs/Log.hpp b/Outputs/Log.hpp index 276cf9e60..22b02f8d0 100644 --- a/Outputs/Log.hpp +++ b/Outputs/Log.hpp @@ -77,7 +77,6 @@ constexpr bool is_enabled(Source source) { case Source::NCR5380: case Source::SCC: case Source::SCSI: - case Source::I2C: return false; } }