Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ca8d4c3
Add a note and todo to the Saleae based sniffer
peternewman Feb 25, 2021
9f868ac
Add some more debugging to the DMXSignalProcessor
peternewman Feb 25, 2021
b8e4500
Check for libsigrok and build the sigrok based sniffer
peternewman Feb 25, 2021
ea599ca
Initial version of sigok based sniffer. Still rather rough around the…
peternewman Feb 25, 2021
dda170d
Add sigrok packages to Travis
peternewman Feb 25, 2021
ead9174
Remove incorrect ifdef wrapper
peternewman Feb 25, 2021
c0c042a
Fix a failed attempt at commenting out an option
peternewman Mar 2, 2021
3c57743
Check for whether libsigrok supports sessions
peternewman Mar 2, 2021
bd689c1
Rename the sigrok context define, add some additional defines
peternewman Mar 2, 2021
f2520b9
First go at handling newer sigrok behaviour
peternewman Mar 2, 2021
26dca5c
Start tidying up some redundant code
peternewman Mar 3, 2021
d048f88
Add a little bit more debug to the DMXSignalProcessor
peternewman Mar 3, 2021
dd3517e
More tidying up of Sigrok code
peternewman Mar 9, 2021
19ccd00
Handle both samples and time based captures
peternewman Mar 9, 2021
3a898b1
Capture continuously by default
peternewman Mar 9, 2021
abf1b5b
Support sigrok's unitsize in the logic packets for LAs with more than…
peternewman Mar 15, 2021
7ac19eb
Make the sigrok device to connect to mandatory
peternewman Mar 15, 2021
6467ca9
Add an initial man file for sigrok-rdm-sniffer
peternewman Mar 15, 2021
8b3fdd0
Fix the case of the sigrok name
peternewman Mar 16, 2021
877f28d
Fix some lint issues
peternewman Mar 16, 2021
b0efa4d
Fix more lint issues
peternewman Mar 16, 2021
2e25f9a
Fix some comments
peternewman Mar 16, 2021
293be8f
Switch sigrok_rdm_sniffer to use our new BaseSnifferReader
peternewman Apr 1, 2021
f7e0099
Fix some lint issues
peternewman Apr 15, 2021
7db2ef2
Switch the original Logic sniffer code to the new common base
peternewman May 20, 2021
1e6b40a
Extract the BaseSnifferReader and DMXSignalProcessor into their own s…
peternewman May 20, 2021
9e9b004
Merge branch 'master' into sigrok
peternewman May 20, 2021
29f3ac2
Fix some lint errors
peternewman May 20, 2021
5f388f3
Update the sniffer READMEs
peternewman May 20, 2021
90e9abf
Merge branch 'OpenLightingProject:master' into sigrok
peternewman Jun 19, 2021
bc94fd4
Merge branch 'master' into sigrok
peternewman Jan 20, 2022
2d01961
Merge branch 'OpenLightingProject:master' into sigrok
peternewman Mar 3, 2023
a725321
Improve an error message
peternewman Mar 5, 2023
363e594
Merge branch 'master' of https://github.com/openlightingproject/ola i…
peternewman Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ tools/rdm/TestRunnerTest.sh
tools/rdm/TestStateTest.sh
tools/rdmpro/rdmpro_sniffer
tools/rdmpro/rdmpro_sniffer.exe
tools/sigrok/sigrok_rdm_sniffer
tools/sigrok/sigrok_rdm_sniffer.exe
tools/slp/slp_client
tools/slp/slp_client.exe
tools/slp/slp_server
Expand Down
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ addons:
- libavahi-glib1
- libncurses5-dev
- libmicrohttpd-dev
- libsigrok-dev
packages: &core_build_clang_recent
- *core_build
- clang-10
Expand Down Expand Up @@ -71,6 +72,7 @@ addons:
# Looks like this is Python 3 only, so install via pip
# - numpy
- libusb
# Sigrok
packages: &mac_cppunit_113
# Installing via the addon isn't currently working so do it the old fashioned way below
# - https://raw.githubusercontent.com/Homebrew/homebrew-core/e6e43cf6a3^/Formula/cppunit.rb # install a slightly older cppunit, as latest needs C++11 support
Expand Down
22 changes: 21 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,29 @@ AS_IF([test "x$have_avahi" = xyes],
[AC_DEFINE([HAVE_AVAHI], [1], [Defined to use Avahi])])
AM_CONDITIONAL([HAVE_AVAHI], [test "x$have_avahi" = xyes])

# Look for -lSaleaeDevice, if we have it we build the logic sniffer.
# Look for -lSaleaeDevice, if we have it we build the Saleae logic sniffer.
SALEAE_DEVICE

# Look for -lsigrok, if we have it we build the sigrok logic sniffer.
PKG_CHECK_MODULES([libsigrok], [libsigrok], [have_libsigrok="yes"], [have_libsigrok="no"])
AM_CONDITIONAL([HAVE_LIBSIGROK],
[test "x$have_libsigrok" = xyes])

have_libsigrok_context="no"
AS_IF([test "x$have_libsigrok" != xno],
[PKG_CHECK_MODULES([libsigrok_context], [libsigrok >= 0.4.0],
[have_libsigrok_context="yes"], [true])])
AS_IF([test "x$have_libsigrok_context" = xyes],
[AC_DEFINE([HAVE_LIBSIGROK_CONTEXT], [1],
[define if libsigrok is installed and uses it's context])])

have_libsigrok_dev_inst_opaque="no"
AS_IF([test "x$have_libsigrok" != xno],
[PKG_CHECK_MODULES([libsigrok_dev_inst_opaque], [libsigrok >= 0.4.0],
[have_libsigrok_dev_inst_opaque="yes"], [true])])
AS_IF([test "x$have_libsigrok_dev_inst_opaque" = xyes],
[AC_DEFINE([HAVE_LIBSIGROK_DEV_INST_OPAQUE], [1],
[define if libsigrok is installed and the sr_dev_inst struct is opaque])])

# Features
#####################################################
Expand Down
1 change: 1 addition & 0 deletions libs/Makefile.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
include libs/acn/Makefile.mk
include libs/sniffer/Makefile.mk
include libs/usb/Makefile.mk
149 changes: 149 additions & 0 deletions libs/sniffer/BaseSnifferReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* BaseSnifferReader.cpp
* Common RDM Sniffer code for logic analyzer based sniffers.
* Copyright (C) 2021 Peter Newman
*/

#include <ola/base/Flags.h>
#include <ola/Callback.h>
#include <ola/Constants.h>
#include <ola/Clock.h>
#include <ola/io/SelectServer.h>
#include <ola/Logging.h>
#include <ola/rdm/CommandPrinter.h>
#include <ola/rdm/PidStoreHelper.h>
#include <ola/rdm/RDMCommand.h>
#include <ola/rdm/RDMPacket.h>
#include <ola/rdm/RDMResponseCodes.h>
#include <ola/StringUtils.h>

#include <iostream>
#include <memory>

#include "libs/sniffer/BaseSnifferReader.h"

using std::auto_ptr;
using std::cerr;
using std::cout;
using std::endl;
using ola::io::SelectServer;
using ola::rdm::CommandPrinter;
using ola::rdm::PidStoreHelper;
using ola::rdm::RDMCommand;
using ola::strings::ToHex;

using ola::NewSingleCallback;

DEFINE_default_bool(display_asc, false,
"Display non-RDM alternate start code frames.");
DEFINE_s_default_bool(full_rdm, r, false, "Unpack RDM parameter data.");
// TODO(Peter): Implement this!
// DEFINE_s_default_bool(timestamp, t, false, "Include timestamps.");
DEFINE_s_default_bool(display_dmx, d, false,
"Display DMX Frames. Defaults to false.");
DEFINE_uint16(dmx_slot_limit, ola::DMX_UNIVERSE_SIZE,
"Only display the first N slots of DMX data.");
DEFINE_string(pid_location, "",
"The directory containing the PID definitions.");

BaseSnifferReader::BaseSnifferReader(SelectServer *ss,
unsigned int sample_rate)
: m_ss(ss),
m_signal_processor(
ola::NewCallback(this, &BaseSnifferReader::FrameReceived),
sample_rate),
m_pid_helper(FLAGS_pid_location.str(), 4),
m_command_printer(&cout, &m_pid_helper) {
if (!m_pid_helper.Init()) {
OLA_WARN << "Failed to init PidStore";
}
}


BaseSnifferReader::~BaseSnifferReader() {
m_ss->DrainCallbacks();
}

void BaseSnifferReader::FrameReceived(const uint8_t *data,
unsigned int length) {
if (!length) {
return;
}

switch (data[0]) {
case ola::DMX512_START_CODE:
DisplayDMXFrame(data + 1, length - 1);
break;
case ola::rdm::START_CODE:
DisplayRDMFrame(data + 1, length - 1);
break;
default:
DisplayAlternateFrame(data, length);
}
}

void BaseSnifferReader::DisplayDMXFrame(const uint8_t *data,
unsigned int length) {
if (!FLAGS_display_dmx) {
return;
}

cout << "DMX " << std::dec;
cout << length << ":" << std::hex;
DisplayRawData(data, length);
}

void BaseSnifferReader::DisplayRDMFrame(const uint8_t *data,
unsigned int length) {
auto_ptr<RDMCommand> command(RDMCommand::Inflate(data, length));
if (command.get()) {
if (FLAGS_full_rdm) {
cout << "---------------------------------------" << endl;
}
command->Print(&m_command_printer, !FLAGS_full_rdm, true);
} else {
cout << "RDM " << std::dec;
cout << length << ":" << std::hex;
DisplayRawData(data, length);
}
}


void BaseSnifferReader::DisplayAlternateFrame(const uint8_t *data,
unsigned int length) {
if (!FLAGS_display_asc || length == 0) {
return;
}

unsigned int slot_count = length - 1;
cout << "SC " << ToHex(static_cast<int>(data[0]))
<< " " << slot_count << ":";
DisplayRawData(data + 1, slot_count);
}


/**
* Dump out the raw data if we couldn't parse it correctly.
*/
void BaseSnifferReader::DisplayRawData(const uint8_t *data,
unsigned int length) {
for (unsigned int i = 0; i < length; i++) {
cout << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<int>(data[i]) << " ";
}
cout << endl;
}
52 changes: 52 additions & 0 deletions libs/sniffer/BaseSnifferReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* BaseSnifferReader.h
* Common RDM Sniffer code for logic analyzer based sniffers.
* Copyright (C) 2021 Peter Newman
*/

#ifndef LIBS_SNIFFER_BASESNIFFERREADER_H_
#define LIBS_SNIFFER_BASESNIFFERREADER_H_

#include <ola/io/SelectServer.h>
#include <ola/rdm/CommandPrinter.h>
#include <ola/rdm/PidStoreHelper.h>

#include "libs/sniffer/DMXSignalProcessor.h"

class BaseSnifferReader {
public:
BaseSnifferReader(ola::io::SelectServer *ss, unsigned int sample_rate);
~BaseSnifferReader();

void FrameReceived(const uint8_t *data, unsigned int length);

virtual void Stop() = 0;

virtual bool IsConnected() const = 0;

protected:
ola::io::SelectServer *m_ss;
DMXSignalProcessor m_signal_processor;
ola::rdm::PidStoreHelper m_pid_helper;
ola::rdm::CommandPrinter m_command_printer;

void DisplayDMXFrame(const uint8_t *data, unsigned int length);
void DisplayRDMFrame(const uint8_t *data, unsigned int length);
void DisplayAlternateFrame(const uint8_t *data, unsigned int length);
void DisplayRawData(const uint8_t *data, unsigned int length);
};
#endif // LIBS_SNIFFER_BASESNIFFERREADER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#include <ola/Logging.h>
#include <vector>

#include "tools/logic/DMXSignalProcessor.h"
#include "libs/sniffer/DMXSignalProcessor.h"

using std::vector;

Expand All @@ -69,6 +69,7 @@ DMXSignalProcessor::DMXSignalProcessor(DataCallback *callback,
m_ticks(0),
m_may_be_in_break(false),
m_ticks_in_break(0) {
OLA_DEBUG << "Microseconds per tick " << m_microseconds_per_tick;
if (m_sample_rate % DMX_BITRATE) {
OLA_WARN << "Sample rate is not a multiple of " << DMX_BITRATE;
}
Expand All @@ -82,10 +83,11 @@ DMXSignalProcessor::DMXSignalProcessor(DataCallback *callback,
* @param size the number of samples in the stream
* @param mask the value to be AND'ed with each sample to determine if the
* signal is high or low.
* @param width the width (in bytes) of each sample within the stream
*/
void DMXSignalProcessor::Process(uint8_t *ptr, unsigned int size,
uint8_t mask) {
for (unsigned int i = 0 ; i < size; i++) {
uint8_t mask, unsigned int width) {
for (unsigned int i = 0 ; i < size; i += width) {
ProcessSample(ptr[i] & mask);
}
}
Expand Down Expand Up @@ -118,7 +120,7 @@ void DMXSignalProcessor::ProcessSample(bool bit) {
SetState(MAB);
} else {
OLA_WARN << "Break too short, was " << TicksAsMicroSeconds()
<< " us";
<< " us (" << m_ticks << " ticks)";
SetState(IDLE);
}
} else {
Expand All @@ -136,7 +138,8 @@ void DMXSignalProcessor::ProcessSample(bool bit) {
// OLA_INFO << "In start bit!";
SetState(START_BIT);
} else {
OLA_WARN << "Mark too short, was " << TicksAsMicroSeconds() << "us";
OLA_WARN << "Mark too short, was " << TicksAsMicroSeconds() << "us ("
<< m_ticks << " ticks)";
SetState(UNDEFINED);
}
}
Expand Down Expand Up @@ -222,7 +225,7 @@ void DMXSignalProcessor::ProcessBit(bool bit) {
SetState(static_cast<State>(m_state + 1));
} else {
OLA_WARN << "Bit " << m_state << " was too short, was "
<< TicksAsMicroSeconds() << "us";
<< TicksAsMicroSeconds() << "us (" << m_ticks << " ticks)";
SetState(UNDEFINED);
}
}
Expand Down Expand Up @@ -283,7 +286,7 @@ void DMXSignalProcessor::HandleFrame() {
*/
void DMXSignalProcessor::SetState(State state, unsigned int ticks) {
OLA_INFO << "Transition to " << state << ", prev duration was "
<< TicksAsMicroSeconds();
<< TicksAsMicroSeconds() << " us (" << m_ticks << " ticks)";
m_state = state;
m_ticks = ticks;
if (state == UNDEFINED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
* Copyright (C) 2013 Simon Newton
*/

#ifndef TOOLS_LOGIC_DMXSIGNALPROCESSOR_H_
#define TOOLS_LOGIC_DMXSIGNALPROCESSOR_H_
#ifndef LIBS_SNIFFER_DMXSIGNALPROCESSOR_H_
#define LIBS_SNIFFER_DMXSIGNALPROCESSOR_H_

#include <ola/Callback.h>
#include <ola/Constants.h>
Expand All @@ -42,7 +42,8 @@ class DMXSignalProcessor {
}

// Process more data.
void Process(uint8_t *ptr, unsigned int size, uint8_t mask = 0xff);
void Process(uint8_t *ptr, unsigned int size, uint8_t mask = 0xff,
unsigned int width = 1);

private:
enum State {
Expand Down Expand Up @@ -106,4 +107,4 @@ class DMXSignalProcessor {
static const double MIN_LAST_BIT_TIME;
static const double MAX_MARK_BETWEEN_SLOTS;
};
#endif // TOOLS_LOGIC_DMXSIGNALPROCESSOR_H_
#endif // LIBS_SNIFFER_DMXSIGNALPROCESSOR_H_
9 changes: 9 additions & 0 deletions libs/sniffer/Makefile.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
noinst_LTLIBRARIES += libs/sniffer/libolasniffer.la

libs_sniffer_libolasniffer_la_SOURCES = \
libs/sniffer/BaseSnifferReader.cpp \
libs/sniffer/BaseSnifferReader.h \
libs/sniffer/DMXSignalProcessor.cpp \
libs/sniffer/DMXSignalProcessor.h
libs_sniffer_libolasniffer_la_CXXFLAGS = $(COMMON_CXXFLAGS)
libs_sniffer_libolasniffer_la_LIBADD = common/libolacommon.la
1 change: 1 addition & 0 deletions man/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ dist_man_MANS += \
man/rdm_responder_test.py.1 \
man/rdm_test_server.py.1 \
man/rdmpro_sniffer.1 \
man/sigrok_rdm_sniffer.1 \
man/usbpro_firmware.1
Loading
Loading