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: 6bd2c1a25d81
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: 1c2bf224765f
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on May 16, 2021

  1. Copy the full SHA
    1c2bf22 View commit details
Showing with 87 additions and 49 deletions.
  1. +7 −35 src/ps6000d/ScpiServerThread.cpp
  2. +39 −14 src/ps6000d/WaveformServerThread.cpp
  3. +28 −0 src/ps6000d/main.cpp
  4. +13 −0 src/ps6000d/ps6000d.h
42 changes: 7 additions & 35 deletions src/ps6000d/ScpiServerThread.cpp
Original file line number Diff line number Diff line change
@@ -153,9 +153,7 @@ size_t g_numDigitalPods = 2;
int16_t g_msoPodThreshold[2][8] = { {0}, {0} };
PICO_DIGITAL_PORT_HYSTERESIS g_msoHysteresis[2] = {PICO_NORMAL_100MV, PICO_NORMAL_100MV};
bool g_msoPodEnabled[2] = {false};

void UpdateTrigger();
void UpdateChannel(size_t chan);
bool g_msoPodEnabledDuringArm[2] = {false};

std::mutex g_mutex;

@@ -196,34 +194,6 @@ bool ScpiRecv(Socket& sock, string& str)
*/
void ScpiServerThread()
{
for(size_t i=0; i<g_numChannels; i++)
{
g_channelOn[i] = false;
g_coupling[i] = PICO_DC;
g_range[i] = PICO_X1_PROBE_1V;
g_range_3000a[i] = PS3000A_1V;
g_offset[i] = 0;
g_bandwidth[i] = PICO_BW_FULL;
g_bandwidth_legacy[i] = PS3000A_BW_FULL;
}

//TODO: detect this somehow
//For now, assume every scope has two MSO pods.
g_numDigitalPods = 2;
for(size_t i=0; i<g_numDigitalPods; i++)
{
g_msoPodEnabled[i] = false;
for(size_t j=0; j<8; j++)
g_msoPodThreshold[i][j] = 0;
g_msoHysteresis[i] = PICO_NORMAL_100MV;
}

//Push initial trigger config
{
lock_guard<mutex> lock(g_mutex);
UpdateTrigger();
}

while(true)
{
Socket client = g_scpiSocket.Accept();
@@ -248,7 +218,7 @@ void ScpiServerThread()
if(!ScpiRecv(client, line))
break;
ParseScpiLine(line, subject, cmd, query, args);
LogVerbose((line + "\n").c_str());
LogTrace((line + "\n").c_str());

//Extract channel ID from subject and clamp bounds
size_t channelId = 0;
@@ -503,7 +473,7 @@ void ScpiServerThread()
else
g_msoHysteresis[channelId] = PICO_VERY_HIGH_400MV;

LogDebug("Setting MSO pod %zu hysteresis to %d mV (code %d)\n",
LogTrace("Setting MSO pod %zu hysteresis to %d mV (code %d)\n",
channelId, level, g_msoHysteresis[channelId]);

//Update the pod if currently active
@@ -677,7 +647,7 @@ void ScpiServerThread()
int16_t code = round( (level * 32767) / 5.0);
g_msoPodThreshold[channelId][laneId] = code;

LogDebug("Setting MSO pod %zu lane %zu threshold to %f (code %d)\n", channelId, laneId, level, code);
LogTrace("Setting MSO pod %zu lane %zu threshold to %f (code %d)\n", channelId, laneId, level, code);

lock_guard<mutex> lock(g_mutex);

@@ -984,13 +954,15 @@ void StartCapture(bool stopFirst)
{
g_offsetDuringArm = g_offset;
g_channelOnDuringArm = g_channelOn;
for(size_t i=0; i<g_numDigitalPods; i++)
g_msoPodEnabledDuringArm[i] = g_msoPodEnabled[i];
g_captureMemDepth = g_memDepth;
g_sampleIntervalDuringArm = g_sampleInterval;
g_triggerSampleIndex = g_memDepth/2;

//TODO: implement g_triggerDelay

LogVerbose("StartCapture stopFirst %d memdepth %zu\n", stopFirst, g_memDepth);
LogTrace("StartCapture stopFirst %d memdepth %zu\n", stopFirst, g_memDepth);

PICO_STATUS status;
status = PICO_RESERVED_1;
53 changes: 39 additions & 14 deletions src/ps6000d/WaveformServerThread.cpp
Original file line number Diff line number Diff line change
@@ -40,6 +40,8 @@ using namespace std;
volatile bool g_waveformThreadQuit = false;
float InterpolateTriggerTime(int16_t* buf);

vector<PICO_CHANNEL> g_channelIDs;

void WaveformServerThread()
{
Socket client = g_dataSocket.Accept();
@@ -50,9 +52,13 @@ void WaveformServerThread()
if(!client.DisableNagle())
LogWarning("Failed to disable Nagle on socket, performance may be poor\n");

//Set up buffers
map<size_t, int16_t*> waveformBuffers;
//Set up channel IDs
for(size_t i=0; i<g_numChannels; i++)
g_channelIDs.push_back((PICO_CHANNEL)i);
for(size_t i=0; i<g_numDigitalPods; i++)
g_channelIDs.push_back((PICO_CHANNEL)(PICO_PORT0 + i));

map<size_t, int16_t*> waveformBuffers;
size_t numSamples = 0;
uint32_t numSamples_int = 0;
uint16_t numchans;
@@ -77,8 +83,7 @@ void WaveformServerThread()
lock_guard<mutex> lock(g_mutex);

//Stop the trigger
PICO_STATUS status;

PICO_STATUS status = PICO_OPERATION_FAILED;
if(g_pico_type == PICO6000A)
status = ps6000aStop(g_hScope);
else if(g_pico_type == PICO3000A)
@@ -93,16 +98,19 @@ void WaveformServerThread()
{
LogDebug("Reallocating buffers\n");

for(size_t i=0; i<g_numChannels; i++)
//Clear out old buffers
for(auto ch : g_channelIDs)
{
if(g_pico_type == PICO6000A)
ps6000aSetDataBuffer(g_hScope, (PICO_CHANNEL)i, NULL,
ps6000aSetDataBuffer(g_hScope, ch, NULL,
0, PICO_INT16_T, 0, PICO_RATIO_MODE_RAW, PICO_CLEAR_ALL);
else if(g_pico_type == PICO3000A)
ps3000aSetDataBuffer(g_hScope, (PS3000A_CHANNEL)i, NULL,
ps3000aSetDataBuffer(g_hScope, (PS3000A_CHANNEL)ch, NULL,
0, 0, PS3000A_RATIO_MODE_NONE);
}
for(size_t i=0; i<g_numChannels; i++)

//Set up new ones
for(size_t i=0; i<g_channelIDs.size(); i++)
{
//Allocate memory if needed
if(waveformBuffers[i])
@@ -111,14 +119,15 @@ void WaveformServerThread()
memset(waveformBuffers[i], 0x00, g_captureMemDepth * sizeof(int16_t));

//Give it to the scope, removing any other buffer we might have
auto ch = g_channelIDs[i];
if(g_pico_type == PICO6000A)
status = ps6000aSetDataBuffer(g_hScope, (PICO_CHANNEL)i, waveformBuffers[i],
status = ps6000aSetDataBuffer(g_hScope, (PICO_CHANNEL)ch, waveformBuffers[i],
g_captureMemDepth, PICO_INT16_T, 0, PICO_RATIO_MODE_RAW, PICO_ADD);
else if(g_pico_type == PICO3000A)
status = ps3000aSetDataBuffer(g_hScope, (PS3000A_CHANNEL)i, waveformBuffers[i],
status = ps3000aSetDataBuffer(g_hScope, (PS3000A_CHANNEL)ch, waveformBuffers[i],
g_captureMemDepth, 0, PS3000A_RATIO_MODE_NONE);
if(status != PICO_OK)
LogFatal("ps6000aSetDataBuffer failed (code 0x%x)\n", status);
LogFatal("psXXXXSetDataBuffer for channel %d failed (code 0x%x)\n", ch, status);
}

g_memDepthChanged = false;
@@ -135,7 +144,7 @@ void WaveformServerThread()
if(status == PICO_NO_SAMPLES_AVAILABLE)
continue; // state changed while mutex was unlocked?
if(PICO_OK != status)
LogFatal("ps6000aGetValues (code 0x%x)\n", status);
LogFatal("psXXXXGetValues (code 0x%x)\n", status);

//Figure out how many channels are active in this capture
numchans = 0;
@@ -144,6 +153,11 @@ void WaveformServerThread()
if(g_channelOnDuringArm[i])
numchans ++;
}
for(size_t i=0; i<g_numDigitalPods; i++)
{
if(g_msoPodEnabled[i])
numchans ++;
}
}

//Send the channel count to the client
@@ -158,9 +172,10 @@ void WaveformServerThread()
float trigphase = InterpolateTriggerTime(waveformBuffers[g_triggerChannel]);

//Send data for each channel to the client
for(size_t i=0; i<g_numChannels; i++)
for(size_t i=0; i<g_channelIDs.size(); i++)
{
if(g_channelOnDuringArm[i])
//Analog channels
if((i < g_numChannels) && (g_channelOnDuringArm[i]) )
{
//Send channel ID, scale, offset, and memory depth
client.SendLooped((uint8_t*)&i, sizeof(i));
@@ -173,6 +188,16 @@ void WaveformServerThread()
//Send the actual waveform data
client.SendLooped((uint8_t*)waveformBuffers[i], numSamples * sizeof(int16_t));
}

//Digital channels
else if( (i >= g_numChannels) && (g_msoPodEnabledDuringArm[i - g_numChannels]) )
{
LogDebug("Sending digital (chnum=%zu)\n", i);
client.SendLooped((uint8_t*)&i, sizeof(i));
client.SendLooped((uint8_t*)&numSamples, sizeof(numSamples));
client.SendLooped((uint8_t*)&trigphase, sizeof(trigphase));
client.SendLooped((uint8_t*)waveformBuffers[i], numSamples * sizeof(int16_t));
}
}

//Re-arm the trigger if doing repeating triggers
28 changes: 28 additions & 0 deletions src/ps6000d/main.cpp
Original file line number Diff line number Diff line change
@@ -253,6 +253,34 @@ int main(int argc, char* argv[])
}
}

//Initialize analog channels
for(size_t i=0; i<g_numChannels; i++)
{
g_channelOn[i] = false;
g_coupling[i] = PICO_DC;
g_range[i] = PICO_X1_PROBE_1V;
g_range_3000a[i] = PS3000A_1V;
g_offset[i] = 0;
g_bandwidth[i] = PICO_BW_FULL;
g_bandwidth_legacy[i] = PS3000A_BW_FULL;
}

//Figure out digital channel configuration
if(g_pico_type == PICO6000A)
g_numDigitalPods = 2;
else
g_numDigitalPods = 0;
for(size_t i=0; i<g_numDigitalPods; i++)
{
g_msoPodEnabled[i] = false;
for(size_t j=0; j<8; j++)
g_msoPodThreshold[i][j] = 0;
g_msoHysteresis[i] = PICO_NORMAL_100MV;
}

//Push initial trigger config
UpdateTrigger();

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

13 changes: 13 additions & 0 deletions src/ps6000d/ps6000d.h
Original file line number Diff line number Diff line change
@@ -74,6 +74,17 @@ extern size_t g_memDepth;
extern std::map<size_t, bool> g_channelOnDuringArm;
extern std::map<size_t, bool> g_channelOn;
extern std::map<size_t, double> g_roundedRange;
extern std::map<size_t, PICO_COUPLING> g_coupling;
extern std::map<size_t, PICO_CONNECT_PROBE_RANGE> g_range;
extern std::map<size_t, enPS3000ARange> g_range_3000a;
extern std::map<size_t, double> g_offset;
extern std::map<size_t, PICO_BANDWIDTH_LIMITER> g_bandwidth;
extern std::map<size_t, size_t> g_bandwidth_legacy;

extern bool g_msoPodEnabled[2];
extern bool g_msoPodEnabledDuringArm[2];
extern int16_t g_msoPodThreshold[2][8];
extern PICO_DIGITAL_PORT_HYSTERESIS g_msoHysteresis[2];

extern uint32_t g_timebase;
extern int64_t g_sampleInterval;
@@ -91,5 +102,7 @@ extern bool g_memDepthChanged;
extern std::mutex g_mutex;

void StartCapture(bool stopFirst);
void UpdateTrigger();
void UpdateChannel(size_t chan);

#endif