Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5b91e7c79d3a
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: aacba8043dc1
Choose a head ref
  • 5 commits
  • 5 files changed
  • 2 contributors

Commits on May 25, 2020

  1. SCPILxiTransport.

    tomverbeure committed May 25, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    50e95f4 View commit details
  2. Copy the full SHA
    46bcc25 View commit details
  3. Copy the full SHA
    1b0c305 View commit details
  4. Copy the full SHA
    b2b9c97 View commit details
  5. Merge pull request #120 from tomverbeure/lxi

    Add SCPILxiTransport class.
    azonenberg authored May 25, 2020
    Copy the full SHA
    aacba80 View commit details
Showing with 274 additions and 1 deletion.
  1. +4 −1 scopehal/CMakeLists.txt
  2. +189 −0 scopehal/SCPILxiTransport.cpp
  3. +75 −0 scopehal/SCPILxiTransport.h
  4. +3 −0 scopehal/scopehal.cpp
  5. +3 −0 scopehal/scopehal.h
5 changes: 4 additions & 1 deletion scopehal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
include_directories(${GTKMM_INCLUDE_DIRS} ${SIGCXX_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS} ${SIGCXX_LIBRARY_DIRS})

find_library(LXI_LIB lxi)

set(SCOPEHAL_SOURCES
base64.cpp
scopehal.cpp
@@ -10,6 +12,7 @@ set(SCOPEHAL_SOURCES
SCPITransport.cpp
SCPISocketTransport.cpp
VICPSocketTransport.cpp
SCPILxiTransport.cpp
SCPIDevice.cpp

Instrument.cpp
@@ -37,7 +40,7 @@ set(SCOPEHAL_SOURCES

add_library(scopehal SHARED
${SCOPEHAL_SOURCES})
target_link_libraries(scopehal ${SIGCXX_LIBRARIES} ${GTKMM_LIBRARIES} xptools log graphwidget yaml-cpp)
target_link_libraries(scopehal ${SIGCXX_LIBRARIES} ${GTKMM_LIBRARIES} xptools log graphwidget yaml-cpp ${LXI_LIB})

target_include_directories(scopehal
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
189 changes: 189 additions & 0 deletions scopehal/SCPILxiTransport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* 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 Andrew D. Zonenberg
@brief Implementation of SCPILxiTransport
*/

#include "scopehal.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

SCPILxiTransport::SCPILxiTransport(string args)
{
char hostname[128];
unsigned int port = 0;
if (2 != sscanf(args.c_str(), "%127[^:]:%u", hostname, &port))
{
//default if port not specified. VXI-11 is port 111, but liblxi fills that in for us.
m_hostname = args;
m_port = 0;
}
else
{
m_hostname = hostname;
m_port = port;
}

m_timeout = 1000;

LogDebug("Connecting to SCPI oscilloscope over VXI-11 at %s:%d\n", m_hostname.c_str(), m_port);

m_device = lxi_connect(m_hostname.c_str(), m_port, "inst0", m_timeout, VXI11);

if (m_device == LXI_ERROR)
{
LogError("Couldn't connect to VXI-11 device\n");
return;
}

// When you issue a lxi_receive request, you need to specify the size of the receiving buffer.
// However, when the data received is larger than this buffer, liblxi simply discards this data.
// ReadReply and ReadRawData expect to be able to fetch received data piecemeal.
// The clunky solution is to have an intermediate buffer that is large enough to store all the
// data that could possible be returned by a scope.
// My Siglent oscilloscope can have a waveform of 140M samples, so I reserve 150M. However,
// I haven't been able to fetch waveforms larger than 1.4M (for reasons unknown.)
// Maybe we should reduce this number...
m_staging_buf_size = 150000000;
m_staging_buf = new char[m_staging_buf_size];
if (m_staging_buf == NULL)
return;
m_data_in_staging_buf = 0;
m_data_offset = 0;
m_data_depleted = false;
}

SCPILxiTransport::~SCPILxiTransport()
{
delete(m_staging_buf);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actual transport code

string SCPILxiTransport::GetTransportName()
{
return "lxi";
}

string SCPILxiTransport::GetConnectionString()
{
char tmp[256];
snprintf(tmp, sizeof(tmp), "%s:%u", m_hostname.c_str(), m_port);
return string(tmp);
}

bool SCPILxiTransport::SendCommand(string cmd)
{
LogTrace("Sending %s\n", cmd.c_str());

int result = lxi_send(m_device, cmd.c_str(), cmd.length(), m_timeout);

m_data_in_staging_buf = 0;
m_data_offset = 0;
m_data_depleted = false;

return (result != LXI_ERROR);
}

string SCPILxiTransport::ReadReply()
{
string ret;

if (!m_staging_buf)
return ret;

//FIXME: there *has* to be a more efficient way to do this...
char tmp = ' ';
while(true)
{
if (m_data_depleted)
break;
ReadRawData(1, (unsigned char *)&tmp);
if( (tmp == '\n') || (tmp == ';') )
break;
else
ret += tmp;
}
LogTrace("Got %s\n", ret.c_str());
return ret;
}

void SCPILxiTransport::SendRawData(size_t len, const unsigned char* buf)
{
// XXX: Should this reset m_data_depleted just like SendCommmand?
lxi_send(m_device, (const char *)buf, len, m_timeout);
}

void SCPILxiTransport::ReadRawData(size_t len, unsigned char* buf)
{
// Data in the staging buffer is assumed to always be a consequence of a SendCommand request.
// Since we fetch all the reply data in one go, once all this data has been fetched, we mark
// the staging buffer as depleted and don't issue a new lxi_receive until a new SendCommand
// is issued.

if (!m_staging_buf)
return;

if (!m_data_depleted)
{
if (m_data_in_staging_buf == 0)
{
m_data_in_staging_buf = lxi_receive(m_device, (char *)m_staging_buf, m_staging_buf_size, m_timeout);
if (m_data_in_staging_buf == LXI_ERROR)
m_data_in_staging_buf = 0;
m_data_offset = 0;
}

unsigned int data_left = m_data_in_staging_buf - m_data_offset;
if (data_left > 0)
{
int nr_bytes = len > data_left ? data_left : len;

memcpy(buf, m_staging_buf + m_data_offset, nr_bytes);

m_data_offset += nr_bytes;
}

if (m_data_offset == m_data_in_staging_buf)
m_data_depleted = true;
}
else
{
// When this happens, the SCPIDevice is fetching more data from device than what
// could be expected from the SendCommand that was issued.
LogDebug("ReadRawData: data depleted.\n");
}
}
75 changes: 75 additions & 0 deletions scopehal/SCPILxiTransport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* 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 Andrew D. Zonenberg
@brief Declaration of SCPILxiTransport
*/

#ifndef SCPILxiTransport_h
#define SCPILxiTransport_h

/**
@brief Abstraction of a transport layer for moving SCPI data between endpoints
*/
class SCPILxiTransport : public SCPITransport
{
public:
SCPILxiTransport(std::string args);
virtual ~SCPILxiTransport();

virtual std::string GetConnectionString();
static std::string GetTransportName();

virtual bool SendCommand(std::string cmd);
virtual std::string ReadReply();
virtual void ReadRawData(size_t len, unsigned char* buf);
virtual void SendRawData(size_t len, const unsigned char* buf);

TRANSPORT_INITPROC(SCPILxiTransport)

std::string GetHostname()
{ return m_hostname; }

protected:
std::string m_hostname;
unsigned short m_port;

int m_device;
int m_timeout;

int m_staging_buf_size;
unsigned char *m_staging_buf;
int m_data_in_staging_buf;
int m_data_offset;
bool m_data_depleted;
};

#endif
3 changes: 3 additions & 0 deletions scopehal/scopehal.cpp
Original file line number Diff line number Diff line change
@@ -51,7 +51,10 @@ using namespace std;
*/
void TransportStaticInit()
{
lxi_init();

AddTransportClass(SCPISocketTransport);
AddTransportClass(SCPILxiTransport);
AddTransportClass(VICPSocketTransport);
}

3 changes: 3 additions & 0 deletions scopehal/scopehal.h
Original file line number Diff line number Diff line change
@@ -46,6 +46,8 @@

#include <yaml-cpp/yaml.h>

#include <lxi.h>

#include "../log/log.h"
#include "../graphwidget/Graph.h"

@@ -55,6 +57,7 @@

#include "SCPITransport.h"
#include "SCPISocketTransport.h"
#include "SCPILxiTransport.h"
#include "VICPSocketTransport.h"
#include "SCPIDevice.h"