diff --git a/scopeprotocols/CMakeLists.txt b/scopeprotocols/CMakeLists.txt index 58758578..37dce387 100644 --- a/scopeprotocols/CMakeLists.txt +++ b/scopeprotocols/CMakeLists.txt @@ -28,6 +28,7 @@ set(SCOPEPROTOCOLS_SOURCES CSVImportFilter.cpp CTLEFilter.cpp CurrentShuntFilter.cpp + DAC8552Decoder.cpp DCDMeasurement.cpp DDJMeasurement.cpp DDR1Decoder.cpp diff --git a/scopeprotocols/DAC8552Decoder.cpp b/scopeprotocols/DAC8552Decoder.cpp new file mode 100644 index 00000000..b08ca089 --- /dev/null +++ b/scopeprotocols/DAC8552Decoder.cpp @@ -0,0 +1,145 @@ + +/*********************************************************************************************************************** +* * +* libscopeprotocols * +* * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * +* following conditions are met: * +* * +* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other materials provided with the distribution. * +* * +* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * +* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * +* POSSIBILITY OF SUCH DAMAGE. * +* * +***********************************************************************************************************************/ + +#include "../scopehal/scopehal.h" +#include "DAC8552Decoder.h" +#include "SPIDecoder.h" + +using namespace std; + +DAC8552Decoder::DAC8552Decoder(const string& color) + : Filter(color, CAT_MISC) +{ + AddProtocolStream("data"); + CreateInput>("spi"); +} + +string DAC8552Waveform::GetColor(size_t) +{ + return m_color; +} + +string DAC8552Waveform::GetText(size_t i) +{ + const DAC8552Symbol& s = m_samples[i]; + + char tmp[128]; + snprintf(tmp, sizeof(tmp), "Load %s %s, Bfr=%c, Value=%d", + s.loadA() ? "A" : "", s.loadB() ? "B" : "", s.bfrSelect() ? 'A' : 'B', s.m_value); + return string(tmp); +} + +string DAC8552Decoder::GetProtocolName() +{ + return "DAC8552"; +} + +void DAC8552Decoder::Refresh( + [[maybe_unused]] vk::raii::CommandBuffer& cmdBuf, + [[maybe_unused]] shared_ptr queue) +{ + ClearMessages(); + + if(!VerifyAllInputsOK()) + { + if(!GetInput(0)) + AddErrorMessage("Missing inputs", "No signal input connected"); + else if(!GetInputWaveform(0)) + AddErrorMessage("Missing inputs", "No waveform available at input"); + SetData(nullptr, 0); + return; + } + + auto din = dynamic_cast(GetInputWaveform(0)); + if(!din) + { + AddErrorMessage("Missing inputs", "Invalid input connected"); + SetData(nullptr, 0); + return; + } + size_t len = din->m_samples.size(); + + auto cap = new DAC8552Waveform(m_displaycolor); + cap->m_timescale = din->m_timescale; + cap->m_startTimestamp = din->m_startTimestamp; + cap->m_startFemtoseconds = din->m_startFemtoseconds; + cap->PrepareForCpuAccess(); + din->PrepareForCpuAccess(); + DAC8552Symbol samp; + int state = 0; + int64_t offset = 0; + + for(size_t i=0; im_samples[i]; + + switch(state) + { + case 0: + if(s.m_stype == SPISymbol::TYPE_SELECT) + state = 1; + break; + case 1: + if(s.m_stype == SPISymbol::TYPE_DATA) + { + offset = din->m_offsets[i]; + samp.m_flags = s.m_data & (DAC8552Symbol::MASK_LOAD_A | DAC8552Symbol::MASK_LOAD_B | DAC8552Symbol::MASK_BFR_SEL); + state = 2; + } else + state = 0; + break; + case 2: + if(s.m_stype == SPISymbol::TYPE_DATA) + { + samp.m_value = static_cast(s.m_data) << 8; + state = 3; + } else + state = 0; + break; + case 3: + if(s.m_stype == SPISymbol::TYPE_DATA) + { + samp.m_value |= s.m_data; + cap->m_offsets.push_back(offset); + cap->m_durations.push_back(din->m_offsets[i] + din->m_durations[i] - offset); + cap->m_samples.push_back(samp); + state = 4; + } else + state = 0; + break; + case 4: + if(s.m_stype == SPISymbol::TYPE_DESELECT) + state = 0; + break; + } + } + cap->MarkSamplesModifiedFromCpu(); + cap->MarkTimestampsModifiedFromCpu(); + SetData(cap, 0); +} diff --git a/scopeprotocols/DAC8552Decoder.h b/scopeprotocols/DAC8552Decoder.h new file mode 100644 index 00000000..4ca07423 --- /dev/null +++ b/scopeprotocols/DAC8552Decoder.h @@ -0,0 +1,85 @@ + +/*********************************************************************************************************************** +* * +* libscopeprotocols * +* * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * +* following conditions are met: * +* * +* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other materials provided with the distribution. * +* * +* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * +* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * +* POSSIBILITY OF SUCH DAMAGE. * +* * +***********************************************************************************************************************/ + +/** + @file + @author Daniel Bauer + @brief Declaration of DAC8552Decoder +*/ +#ifndef DAC8522Decoder_h +#define DAC8522Decoder_h + +class DAC8552Symbol +{ +public: + DAC8552Symbol(uint8_t flags = 0, uint16_t value=0xDEAD) + : m_flags(flags) + , m_value(value) + {} + // Rather store all the flags in 1 byte instead of making the struct 5 bytes large and then get funky padding + // This will most likely get padded to a nice handy integer + static constexpr uint8_t MASK_LOAD_A = 0x10; + static constexpr uint8_t MASK_LOAD_B = 0x20; + static constexpr uint8_t MASK_BFR_SEL = 0x04; + uint8_t m_flags; + uint16_t m_value; + + bool operator==(const DAC8552Symbol& s) const + { + return (m_flags == s.m_flags) && (m_value == s.m_value); + } + bool loadA() const { return m_flags & MASK_LOAD_A ? true : false; } + bool loadB() const { return m_flags & MASK_LOAD_B ? true : false; } + bool bfrSelect() const { return m_flags & MASK_BFR_SEL ? true : false; } +}; + +class DAC8552Waveform : public SparseWaveform +{ +public: + DAC8552Waveform (const std::string& color) : SparseWaveform(), m_color(color) {}; + virtual std::string GetText(size_t override); + virtual std::string GetColor(size_t override); + +private: + const std::string& m_color; +}; + +class DAC8552Decoder : public Filter +{ +public: + DAC8552Decoder(const std::string& color); + + virtual void Refresh(vk::raii::CommandBuffer& cmdBuf, std::shared_ptr queue) override; + static std::string GetProtocolName(); + + PROTOCOL_DECODER_INITPROC(DAC8552Decoder) +}; + +#endif diff --git a/scopeprotocols/scopeprotocols.cpp b/scopeprotocols/scopeprotocols.cpp index 6d2ebeb9..644a8701 100644 --- a/scopeprotocols/scopeprotocols.cpp +++ b/scopeprotocols/scopeprotocols.cpp @@ -69,6 +69,7 @@ void ScopeProtocolStaticInit() AddDecoderClass(CSVImportFilter); AddDecoderClass(CTLEFilter); AddDecoderClass(CurrentShuntFilter); + AddDecoderClass(DAC8552Decoder); AddDecoderClass(DCDMeasurement); AddDecoderClass(DDJMeasurement); AddDecoderClass(DDR1Decoder); diff --git a/scopeprotocols/scopeprotocols.h b/scopeprotocols/scopeprotocols.h index 3daee910..fa9f1da8 100644 --- a/scopeprotocols/scopeprotocols.h +++ b/scopeprotocols/scopeprotocols.h @@ -68,6 +68,7 @@ #include "CSVImportFilter.h" #include "CTLEFilter.h" #include "CurrentShuntFilter.h" +#include "DAC8552Decoder.h" #include "DCDMeasurement.h" #include "DDJMeasurement.h" #include "DDR1Decoder.h"