From 4d365b42fa15742762ef1879741100cfaecb3cad Mon Sep 17 00:00:00 2001 From: Christoph Mair Date: Mon, 7 Sep 2026 04:27:42 +0200 Subject: [PATCH] I2CDecoder: add I2C address justification setting Add a UI setting to select left or right justified I2C addresses. The (new) default is right justified. Actual bus data is not changed. A downstream I2CRegisterDecoder uses the same address format as the upstream I2CDecoder. --- scopeprotocols/I2CDecoder.cpp | 13 ++++++++++--- scopeprotocols/I2CDecoder.h | 9 +++++++++ scopeprotocols/I2CRegisterDecoder.cpp | 13 +++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/scopeprotocols/I2CDecoder.cpp b/scopeprotocols/I2CDecoder.cpp index 004c002f..f52bb8e0 100644 --- a/scopeprotocols/I2CDecoder.cpp +++ b/scopeprotocols/I2CDecoder.cpp @@ -45,9 +45,15 @@ using namespace std; I2CDecoder::I2CDecoder(const string& color) : PacketDecoder(color, CAT_BUS) + , m_addrFormat(m_parameters["Address Format"]) { CreateInput("sda", Stream::STREAM_TYPE_DIGITAL); CreateInput("scl", Stream::STREAM_TYPE_DIGITAL); + + m_addrFormat = FilterParameter(FilterParameter::TYPE_ENUM, Unit(Unit::UNIT_COUNTS)); + m_addrFormat.AddEnumValue("Right Justified", RIGHT); + m_addrFormat.AddEnumValue("Left Justified", LEFT); + m_addrFormat.SetIntVal(RIGHT); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -203,7 +209,7 @@ void I2CDecoder::InnerLoop(T* sda, U* scl, I2CWaveform* cap) if(pack) { - pack->m_headers["Address"] = to_string_hex(current_byte & 0xfe); + pack->m_headers["Address"] = to_string_hex((LEFT == m_addrFormat.GetIntVal()) ? (current_byte & 0xfe) : (current_byte >> 1)); if(current_byte & 1) { pack->m_headers["Op"] = "Read"; @@ -312,6 +318,7 @@ void I2CDecoder::Refresh( auto cap = SetupEmptyWaveform(sda, 0); cap->m_timescale = 1; cap->m_triggerPhase = 0; + cap->m_addrFormat = m_addrFormat.GetIntVal(); cap->PrepareForCpuAccess(); if(usda && uscl) @@ -378,9 +385,9 @@ string I2CWaveform::GetText(size_t i) break; case I2CSymbol::TYPE_ADDRESS: if(s.m_data & 1) - snprintf(tmp, sizeof(tmp), "R:%02x", s.m_data & 0xfe); + snprintf(tmp, sizeof(tmp), "R:%02x", (I2CDecoder::LEFT == m_addrFormat) ? (s.m_data & 0xfe) : (s.m_data >> 1)); else - snprintf(tmp, sizeof(tmp), "W:%02x", s.m_data & 0xfe); + snprintf(tmp, sizeof(tmp), "W:%02x", (I2CDecoder::LEFT == m_addrFormat) ? (s.m_data & 0xfe) : (s.m_data >> 1)); break; case I2CSymbol::TYPE_DATA: snprintf(tmp, sizeof(tmp), "%02x", s.m_data); diff --git a/scopeprotocols/I2CDecoder.h b/scopeprotocols/I2CDecoder.h index 77761056..1f2344d6 100644 --- a/scopeprotocols/I2CDecoder.h +++ b/scopeprotocols/I2CDecoder.h @@ -76,11 +76,19 @@ class I2CWaveform : public SparseWaveform I2CWaveform () : SparseWaveform() {}; virtual std::string GetText(size_t) override; virtual std::string GetColor(size_t) override; + + uint8_t m_addrFormat = 0; }; class I2CDecoder : public PacketDecoder { public: + enum AddressJustification + { + RIGHT, + LEFT + }; + I2CDecoder(const std::string& color); virtual void Refresh(vk::raii::CommandBuffer& cmdBuf, std::shared_ptr queue) override; @@ -92,6 +100,7 @@ class I2CDecoder : public PacketDecoder PROTOCOL_DECODER_INITPROC(I2CDecoder) protected: + FilterParameter& m_addrFormat; template void InnerLoop(T* sda, U* scl, I2CWaveform* cap); }; diff --git a/scopeprotocols/I2CRegisterDecoder.cpp b/scopeprotocols/I2CRegisterDecoder.cpp index 65333961..7c1cf5cf 100644 --- a/scopeprotocols/I2CRegisterDecoder.cpp +++ b/scopeprotocols/I2CRegisterDecoder.cpp @@ -49,7 +49,7 @@ I2CRegisterDecoder::I2CRegisterDecoder(const string& color) m_addrbytes.SetIntVal(1); m_baseaddr = FilterParameter(FilterParameter::TYPE_INT, Unit(Unit::UNIT_HEXNUM)); - m_baseaddr.SetIntVal(0x90); + m_baseaddr.SetIntVal(0x48); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -100,6 +100,15 @@ void I2CRegisterDecoder::Refresh( din->PrepareForCpuAccess(); + //The bus address is entered in the same format displayed by the upstream I2C decoder: + //either right (no R/W bit) or left justified (with the R/W bit in bit 0). + //The raw bus byte from the I2C decoder is left justified, so extract the address bits + //from it and compare against the address exactly as entered. + auto GetAddressBits = [&] (uint8_t data) + { + return (I2CDecoder::LEFT == din->m_addrFormat) ? (data & 0xfe) : (data >> 1); + }; + //Pull out our settings uint8_t base_addr = m_baseaddr.GetIntVal(); int pointer_bytes = m_addrbytes.GetIntVal(); @@ -153,7 +162,7 @@ void I2CRegisterDecoder::Refresh( if(s.m_stype == I2CSymbol::TYPE_ADDRESS) { //If address bits don't match, discard it - if( (s.m_data & 0xfe) != base_addr) + if( GetAddressBits(s.m_data) != base_addr) { state = 0; continue;