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-pico-bridge
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d3df0cc1453a
Choose a base ref
...
head repository: ngscopeclient/scopehal-pico-bridge
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 923b8dfb431b
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Mar 14, 2021

  1. Copy the full SHA
    923b8df View commit details
Showing with 132 additions and 5 deletions.
  1. +111 −2 src/ps6000d/ScpiServerThread.cpp
  2. +6 −1 src/ps6000d/WaveformServerThread.cpp
  3. +15 −2 src/ps6000d/main.cpp
113 changes: 111 additions & 2 deletions src/ps6000d/ScpiServerThread.cpp
Original file line number Diff line number Diff line change
@@ -78,6 +78,18 @@
STOP
Disarms the trigger
TRIG:DELAY [delay]
Sets trigger delay (in fs)
TRIG:EDGE:DIR [direction]
Sets trigger direction. Legal values are RISING, FALLING, or ANY.
TRIG:LEV [level]
Selects trigger level (in volts)
TRIG:SOU [chan]
Selects the channel as the trigger source
*/

#include "ps6000d.h"
@@ -111,6 +123,13 @@ bool g_triggerArmed = false;
bool g_triggerOneShot = false;
bool g_memDepthChanged = false;

//Trigger state (for now, only simple single-channel trigger supported)
uint64_t g_triggerDelay = 0;
PICO_THRESHOLD_DIRECTION g_triggerDirection = PICO_RISING;
float g_triggerVoltage = 0;
size_t g_triggerChannel = 0;

void UpdateTrigger();
void UpdateChannel(size_t chan);

std::mutex g_mutex;
@@ -161,6 +180,9 @@ void ScpiServerThread()
g_bandwidth[i] = PICO_BW_FULL;
}

//Push initial trigger config
UpdateTrigger();

while(true)
{
Socket client = g_scpiSocket.Accept();
@@ -382,8 +404,13 @@ void ScpiServerThread()
}

//LogDebug("Requested %f V full-scale range. Got %f\n", range, g_roundedRange[channelId]);

UpdateChannel(channelId);

//Update trigger if this is the trigger channel.
//Trigger is digital and threshold is specified in ADC counts.
//We want to maintain constant trigger level in volts, not ADC counts.
if(g_triggerChannel == channelId)
UpdateTrigger();
}

else if( (cmd == "RATE") && (args.size() == 1) )
@@ -459,6 +486,56 @@ void ScpiServerThread()
g_triggerArmed = false;
}

else if(subject == "TRIG")
{
if( (cmd == "EDGE:DIR") && (args.size() == 1) )
{
lock_guard<mutex> lock(g_mutex);

if(args[0] == "RISING")
g_triggerDirection = PICO_RISING;
else if(args[0] == "FALLING")
g_triggerDirection = PICO_FALLING;
else if(args[0] == "ANY")
g_triggerDirection = PICO_RISING_OR_FALLING;

UpdateTrigger();
}

else if( (cmd == "LEV") && (args.size() == 1) )
{
lock_guard<mutex> lock(g_mutex);

g_triggerVoltage = stof(args[0]);
UpdateTrigger();
}

else if( (cmd == "SOU") && (args.size() == 1) )
{
lock_guard<mutex> lock(g_mutex);
g_triggerChannel = args[0][0] - 'A';

UpdateTrigger();
}

else if( (cmd == "DELAY") && (args.size() == 1) )
{
lock_guard<mutex> lock(g_mutex);

g_triggerDelay = stoull(args[0]);
UpdateTrigger();
}

else
{
LogDebug("Unrecognized trigger command received: %s\n", line.c_str());
LogIndenter li;
LogDebug("Command: %s\n", cmd.c_str());
for(auto arg : args)
LogDebug("Arg: %s\n", arg.c_str());
}
}

//TODO: bandwidth limiter

//Unknown
@@ -498,7 +575,8 @@ void ParseScpiLine(const string& line, string& subject, string& cmd, bool& query
{
//If there's no colon in the command, the first block is the command.
//If there is one, the first block is the subject and the second is the command.
if(line[i] == ':')
//If more than one, treat it as freeform text in the command.
if( (line[i] == ':') && subject.empty() )
{
subject = tmp;
tmp = "";
@@ -556,3 +634,34 @@ void UpdateChannel(size_t chan)
else
ps6000aSetChannelOff(g_hScope, (PICO_CHANNEL)chan);
}

/**
@brief Pushes trigger configuration to the instrument
*/
void UpdateTrigger()
{
//Convert threshold from volts to ADC counts
float offset = g_offset[g_triggerChannel];
float scale = g_roundedRange[g_triggerChannel] / 32512;
float trig_code = (g_triggerVoltage - offset) / scale;

//TODO: Convert delay from fs to native units (samples? ps?)
uint64_t delay = 0;

ps6000aSetSimpleTrigger(
g_hScope,
1,
(PICO_CHANNEL)g_triggerChannel,
round(trig_code),
g_triggerDirection,
delay,
0);

if(g_triggerArmed)
{
ps6000aStop(g_hScope);
auto status = ps6000aRunBlock(g_hScope, g_memDepth/2, g_memDepth/2, g_timebase, NULL, 0, NULL, NULL);
if(status != PICO_OK)
LogFatal("ps6000aRunBlock failed, code %d\n", status);
}
}
7 changes: 6 additions & 1 deletion src/ps6000d/WaveformServerThread.cpp
Original file line number Diff line number Diff line change
@@ -159,7 +159,12 @@ void WaveformServerThread()
//Restart
auto status = ps6000aRunBlock(g_hScope, g_captureMemDepth/2, g_captureMemDepth/2,
g_timebase, NULL, 0, NULL, NULL);
if(status != PICO_OK)
if(status == PICO_HARDWARE_CAPTURING_CALL_STOP)
{
//A start command was received from the socket thread.
//No need to start again
}
else if(status != PICO_OK)
LogFatal("ps6000aRunBlock in WaveformServerThread failed, code %d\n", status);
}
}
17 changes: 15 additions & 2 deletions src/ps6000d/main.cpp
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
*/

#include "ps6000d.h"
#include <signal.h>

using namespace std;

@@ -72,6 +73,8 @@ size_t g_numChannels = 0;
Socket g_scpiSocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
Socket g_dataSocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);

void OnQuit(int signal);

int main(int argc, char* argv[])
{
//Global settings
@@ -217,6 +220,9 @@ int main(int argc, char* argv[])
for(size_t i=0; i<g_numChannels; i++)
ps6000aSetChannelOff(g_hScope, (PICO_CHANNEL)i);

//Set up signal handlers
signal(SIGINT, OnQuit);

//Configure the data plane socket
g_dataSocket.Bind(waveform_port);
g_dataSocket.Listen();
@@ -226,9 +232,16 @@ int main(int argc, char* argv[])
g_scpiSocket.Listen();
ScpiServerThread();

//TODO: proper clean shutdown with ^C?

//Done
ps6000aCloseUnit(g_hScope);
return 0;
}

void OnQuit(int /*signal*/)
{
LogNotice("Shutting down...\n");

lock_guard<mutex> lock(g_mutex);
ps6000aCloseUnit(g_hScope);
exit(0);
}