Add channel controls to scope

master
Timothy Pearson 13 years ago
parent 3ce46cc90f
commit 23eadbf924

@ -48,10 +48,27 @@ void InstrumentView::init() {
m_instrumentPart = (InstrumentPart *)factory->create(TQT_TQOBJECT(this), "part", "KParts::RemoteInstrumentPart");
connect(m_instrumentPart, SIGNAL(statusMessageSet(const TQString&)), this, SLOT(setStatusMessage(const TQString&)));
connect(m_instrumentPart, SIGNAL(usingFixedSizeChanged(bool)), this, SLOT(setUsingFixedSize(bool)));
connect(m_instrumentPart, SIGNAL(resizeToHintRequested()), this, SLOT(setChildSizeToHint()));
TQWidget *childPartWidget = m_instrumentPart->widget();
if (childPartWidget) {
childPartWidget->installEventFilter(this);
}
}
}
bool InstrumentView::eventFilter(TQObject *o, TQEvent *e) {
TQWidget *childPartWidget = m_instrumentPart->widget();
if (childPartWidget) {
if (o == childPartWidget) {
if (e->type() == TQEvent::Resize) {
setChildSizeToHint();
}
}
}
// Allow event processing by other routines
return FALSE;
}
void InstrumentView::setChildSizeToHint() {
if (m_instrumentPart) {
TQWidget *childPartWidget = m_instrumentPart->widget();
@ -62,7 +79,7 @@ void InstrumentView::setChildSizeToHint() {
else {
TQSize childSizeHint = childPartWidget->sizeHint();
setMinimumSize(childSizeHint.width(), childSizeHint.height());
childPartWidget->resize(size());
resize(childPartWidget->size());
}
}
}

@ -34,6 +34,7 @@ class InstrumentView : public KMdiChildView
virtual void readProperties(KConfig *);
virtual bool queryExit();
virtual void resizeEvent(TQResizeEvent *);
virtual bool eventFilter(TQObject *o, TQEvent *e);
private slots:
void setStatusMessage(const TQString& message);

@ -98,63 +98,15 @@
</widget>
<widget class="TQGroupBox" row="0" column="1">
<property name="name">
<cstring>groupOscilloscopeTraceControls</cstring>
<cstring>groupOscilloscopeCaptureControls</cstring>
</property>
<property name="title">
<string>Receiver Controls</string>
<string>Capture Controls</string>
</property>
<grid>
<widget class="TQLabel" row="0" column="0" colspan="1">
<widget class="TQWidget" row="0" column="0" colspan="4">
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="text">
<string>Reference Power Level:</string>
</property>
<property name="textFormat">
<enum>PlainText</enum>
</property>
</widget>
<widget class="FloatSpinBox" row="0" column="1" colspan="1">
<property name="name">
<cstring>saRefLevel</cstring>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>3</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maxValue">
<number>128</number>
</property>
<property name="minValue">
<number>-128</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
<widget class="TQLabel" row="0" column="3" colspan="1">
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="text">
<string>dBm</string>
</property>
<property name="textFormat">
<enum>PlainText</enum>
<cstring>traceControlLayoutWidget</cstring>
</property>
</widget>
</grid>

@ -18,6 +18,9 @@
#include <tqsocket.h>
#include <tqmutex.h>
#include <tqgroupbox.h>
#include <tqlayout.h>
#include <tqcombobox.h>
#include <tqcheckbox.h>
#include <tqpushbutton.h>
#include <tqeventloop.h>
#include <tqapplication.h>
@ -38,19 +41,23 @@ struct exit_exception {
};
enum connectionStates {
ScopeState_InitialRequest = 0,
ScopeState_ResetRequest = 2,
ScopeState_HorizontalDivCountRequest = 4,
ScopeState_VerticalDivCountRequest = 6,
ScopeState_ChannelCountRequest = 8,
ScopeState_ChannelActiveStateRequest = 10,
ScopeState_TraceSampleCountRequest = 12,
ScopeState_TraceVoltsDivRequest = 14,
ScopeState_TraceSecondsDivRequest = 16,
ScopeState_TriggerChannelRequest = 18,
ScopeState_TriggerLevelRequest = 20,
ScopeState_TraceRequest = 50,
ScopeState_ExternalCommandRequest = 255
ScopeState_InitialRequest = 0,
ScopeState_ResetRequest = 2,
ScopeState_HorizontalDivCountRequest = 4,
ScopeState_VerticalDivCountRequest = 6,
ScopeState_ChannelCountRequest = 8,
ScopeState_ChannelActiveStateRequest = 10,
ScopeState_TraceSampleCountRequest = 12,
ScopeState_TracePermittedVoltsDivRequest = 14,
ScopeState_TraceVoltsDivRequest = 16,
ScopeState_TraceSecondsDivRequest = 18,
ScopeState_TriggerChannelRequest = 20,
ScopeState_TriggerLevelRequest = 22,
ScopeState_TraceRequest = 50,
ScopeState_ChannelActiveStateUpdate = 100,
ScopeState_TraceVoltsDivUpdate = 102,
ScopeState_TriggerLevelUpdate = 104,
ScopeState_ExternalCommandRequest = 255
};
namespace RemoteLab {
@ -59,6 +66,80 @@ typedef KParts::GenericFactory<RemoteLab::ScopePart> Factory;
#define CLIENT_LIBRARY "libremotelab_scope"
K_EXPORT_COMPONENT_FACTORY( libremotelab_scope, RemoteLab::Factory )
TraceControlWidget::TraceControlWidget(TQWidget *parent, const char *name)
: TQWidget(parent, name)
{
TQGridLayout *topGrid = new TQGridLayout(this);
m_groupBox = new TQGroupBox(this);
m_groupBox->setColumnLayout(0, TQt::Vertical);
topGrid->addMultiCellWidget(m_groupBox, 0, 0, 0, 0);
m_groupBox->setTitle(i18n("Unknown Channel"));
m_primaryLayout = new TQGridLayout(m_groupBox->layout(), KDialog::marginHint(), KDialog::spacingHint());
m_channelEnabledCheckBox = new TQCheckBox(m_groupBox);
connect(m_channelEnabledCheckBox, SIGNAL(clicked()), this, SLOT(enableClicked()));
m_channelEnabledCheckBox->setText(i18n("Enable"));
m_primaryLayout->addMultiCellWidget(m_channelEnabledCheckBox, 0, 0, 0, 0);
m_voltsDivComboBox = new TQComboBox(m_groupBox);
connect(m_voltsDivComboBox, SIGNAL(activated(int)), this, SLOT(vdivChanged(int)));
m_primaryLayout->addMultiCellWidget(m_voltsDivComboBox, 0, 0, 1, 1);
TQLabel* label = new TQLabel(m_groupBox);
label->setText(i18n("V/div"));
m_primaryLayout->addMultiCellWidget(label, 0, 0, 2, 2);
}
TraceControlWidget::~TraceControlWidget() {
//
}
void TraceControlWidget::setVoltsPerDivList(TQDoubleList list) {
m_voltsDivList = list;
// Update drop down list
double prevValue = m_voltsDivComboBox->currentText().toDouble();
m_voltsDivComboBox->clear();
TQDoubleList::iterator it;
int i = 0;
for (it = m_voltsDivList.begin(); it != m_voltsDivList.end(); ++it) {
m_voltsDivComboBox->insertItem(TQString("%1").arg(*it), i);
if (prevValue == (*it)) {
m_voltsDivComboBox->setCurrentItem(i);
}
i++;
}
}
void TraceControlWidget::setSelectedVoltsPerDiv(double vdiv) {
int i = 0;
for (i=0;i<m_voltsDivComboBox->count();i++) {
if (m_voltsDivComboBox->text(i).toDouble() == vdiv) {
m_voltsDivComboBox->setCurrentItem(i);
}
}
}
void TraceControlWidget::setTraceEnabled(bool enabled) {
m_channelEnabledCheckBox->setChecked(enabled);
m_voltsDivComboBox->setEnabled(enabled);
}
void TraceControlWidget::setTraceName(TQString name) {
m_groupBox->setTitle(name);
}
void TraceControlWidget::enableClicked() {
bool enabled = m_channelEnabledCheckBox->isOn();
m_voltsDivComboBox->setEnabled(enabled);
emit(enableChanged(enabled));
}
void TraceControlWidget::vdivChanged(int index) {
Q_UNUSED(index)
double value = m_voltsDivComboBox->currentText().toDouble();
emit(voltsPerDivChanged(value));
}
ScopePart::ScopePart( TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const TQStringList& )
: RemoteInstrumentPart( parent, name ), m_traceWidget(0), m_commHandlerState(-1), m_commHandlerMode(0), m_commHandlerCommandState(0), m_connectionActiveAndValid(false),
@ -88,11 +169,18 @@ ScopePart::ScopePart( TQWidget *parentWidget, const char *widgetName, TQObject *
m_channelActive[traceno] = false;
m_voltsDiv[traceno] = 0;
m_secsDiv[traceno] = 0;
m_traceControlWidgetList[traceno] = NULL;
m_voltsDivSet[traceno] = false;
m_channelActiveSet[traceno] = false;
}
m_triggerLevelSet = false;
// Create widgets
m_base = new ScopeBase(widget());
m_traceControlWidgetGrid = new TQGridLayout(m_base->traceControlLayoutWidget);
m_traceWidget = m_base->traceWidget;
connect(m_traceWidget, SIGNAL(cursorDragged(uint, double)), this, SLOT(cursorLevelChanged(uint, double)));
m_traceWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding));
m_traceWidget->setNumberOfCursors(5);
m_traceWidget->setZoomCursorStartIndex(1);
@ -132,19 +220,12 @@ ScopePart::ScopePart( TQWidget *parentWidget, const char *widgetName, TQObject *
connect(m_traceWidget, SIGNAL(zoomBoxChanged(const TQRectF&)), this, SLOT(updateZoomWidgetLimits(const TQRectF&)));
connect(m_traceWidget, SIGNAL(offsetChanged(uint, double)), m_base->traceZoomWidget, SLOT(setTraceOffset(uint, double)));
m_base->saRefLevel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
m_base->saRefLevel->setFloatMin(-128);
m_base->saRefLevel->setFloatMax(128);
m_base->saRefLevel->setLineStep(1);
connect(m_base->acqStart, SIGNAL(clicked()), this, SLOT(startDAQ()));
connect(m_base->acqStop, SIGNAL(clicked()), this, SLOT(stopDAQ()));
connect(m_base->waveformSave, SIGNAL(clicked()), this, SLOT(saveWaveforms()));
connect(m_base->waveformRecall, SIGNAL(clicked()), this, SLOT(recallWaveforms()));
connect(m_base->saRefLevel, SIGNAL(floatValueChanged(double)), this, SLOT(saRefLevelChanged(double)));
TQTimer::singleShot(0, this, TQT_SLOT(postInit()));
}
@ -190,11 +271,11 @@ void ScopePart::processLockouts() {
}
// Middle area
if ((m_commHandlerMode < 2) && (m_commHandlerState < 50)) {
m_base->groupOscilloscopeTraceControls->setEnabled(false);
if (((m_commHandlerMode < 2) && (m_commHandlerState < 50)) || (stopTraceUpdate)) {
m_base->groupOscilloscopeCaptureControls->setEnabled(false);
}
else {
m_base->groupOscilloscopeTraceControls->setEnabled(true);
m_base->groupOscilloscopeCaptureControls->setEnabled(true);
}
// Least area
@ -237,6 +318,14 @@ void ScopePart::connectionStatusChangedCallback() {
}
void ScopePart::setTickerMessage(TQString message) {
int i;
bool updatesPending = false;
for (i=0; i<=MAXTRACES;i++) {
if (m_channelActiveSet[i]) updatesPending = true;
if (m_voltsDivSet[i]) updatesPending = true;
if (m_triggerLevelSet) updatesPending = true;
}
m_connectionActiveAndValid = true;
TQString tickerChar;
switch (m_tickerState) {
@ -253,7 +342,12 @@ void ScopePart::setTickerMessage(TQString message) {
tickerChar = "/";
break;
}
setStatusMessage(message + TQString("... %1").arg(tickerChar));
if (updatesPending) {
setStatusMessage(i18n("Updates pending") + ", " + message + TQString("... %1").arg(tickerChar));
}
else {
setStatusMessage(message + TQString("... %1").arg(tickerChar));
}
m_tickerState++;
if (m_tickerState > 3) {
m_tickerState = 0;
@ -474,6 +568,7 @@ void ScopePart::mainEventLoop() {
if (m_maxNumberOfTraces > MAXTRACES) {
m_maxNumberOfTraces = MAXTRACES;
}
updateTraceControlWidgets();
}
m_socket->clearFrameTail();
@ -572,6 +667,54 @@ void ScopePart::mainEventLoop() {
if (m_currentOpChannel > 0) {
SET_NEXT_STATE(ScopeState_TraceSampleCountRequest)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
SET_NEXT_STATE(ScopeState_TracePermittedVoltsDivRequest)
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
COMMUNICATIONS_FAILED
}
}
else {
if (!m_updateTimeoutTimer->isActive()) {
UPDATEDISPLAY_TIMEOUT
}
}
}
else if (m_commHandlerState == ScopeState_TracePermittedVoltsDivRequest) {
// Get permitted volts/div settings, step 1
ds << TQString("GETPERMITTEDVDIVS");
ds << m_currentOpChannel;
m_socket->writeEndOfFrame();
SET_NEXT_STATE(ScopeState_TracePermittedVoltsDivRequest+1)
EXEC_NEXT_STATE_IMMEDIATELY
}
else if (m_commHandlerState == ScopeState_TracePermittedVoltsDivRequest+1) {
// Get response data
if (m_socket->canReadFrame()) {
PAT_WATCHDOG_TIMER
setTickerMessage(i18n("Loading [Received allowed V/div list for channel %1]").arg(m_currentOpChannel));
// Get permitted volts/div settings, step 2
TQString result;
ds >> result;
if (result == "ACK") {
TQDoubleList list;
ds >> list;
if (m_traceControlWidgetList[m_currentOpChannel-1]) {
m_traceControlWidgetList[m_currentOpChannel-1]->setVoltsPerDivList(list);
}
}
m_socket->clearFrameTail();
if (result == "ACK") {
if (m_currentOpChannel < m_maxNumberOfTraces) {
m_currentOpChannel++;
SET_NEXT_STATE(ScopeState_TracePermittedVoltsDivRequest)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
SET_NEXT_STATE(ScopeState_TraceVoltsDivRequest)
@ -645,7 +788,7 @@ void ScopePart::mainEventLoop() {
// Get response data
if (m_socket->canReadFrame()) {
PAT_WATCHDOG_TIMER
setTickerMessage(i18n("Loading [Received seconds/div]"));
setTickerMessage(i18n("Loading [Received seconds/div for channel %1]").arg(m_currentOpChannel));
// Get seconds per division, step 2
TQString result;
@ -738,9 +881,6 @@ void ScopePart::mainEventLoop() {
if (result == "ACK") {
// Update display widget(s)
updateGraticule();
// HACK
// Force resize of parent frame
emit(resizeToHintRequested());
}
if (result == "ACK") {
@ -764,6 +904,7 @@ void ScopePart::mainEventLoop() {
ds << m_currentOpChannel;
m_socket->writeEndOfFrame();
m_lastChangesRequireFullUpdate = false;
SET_NEXT_STATE(ScopeState_TraceRequest+1)
EXEC_NEXT_STATE_IMMEDIATELY
}
@ -797,12 +938,16 @@ void ScopePart::mainEventLoop() {
if (result == "ACK") {
m_currentOpChannel = getNextActiveChannel(m_currentOpChannel, m_channelActive, m_maxNumberOfTraces);
if (m_currentOpChannel > 0) {
if ((m_currentOpChannel > 0)
&& (m_channelActiveSet[m_currentOpChannel] == false)
&& (m_voltsDivSet[m_currentOpChannel] == false)
&& (m_triggerLevelSet == false)
) {
SET_NEXT_STATE(ScopeState_TraceRequest)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
SET_NEXT_STATE(ScopeState_TraceRequest)
SET_NEXT_STATE(ScopeState_ChannelActiveStateUpdate)
}
EXEC_NEXT_STATE_IMMEDIATELY
}
@ -816,6 +961,168 @@ void ScopePart::mainEventLoop() {
}
}
}
else if (m_commHandlerState == ScopeState_ChannelActiveStateUpdate) {
if (m_channelActiveSet[m_currentOpChannel]) {
// Set channel active, step 1
ds << TQString("SETCHANNELACTIVE");
ds << m_currentOpChannel;
TQ_INT16 active = (m_channelActive[m_currentOpChannel])?1:0;
ds << active;
m_socket->writeEndOfFrame();
m_lastChangesRequireFullUpdate = true;
m_channelActiveSet[m_currentOpChannel] = false;
SET_NEXT_STATE(ScopeState_ChannelActiveStateUpdate+1)
}
else {
if (m_currentOpChannel < m_maxNumberOfTraces) {
m_currentOpChannel++;
SET_NEXT_STATE(ScopeState_ChannelActiveStateUpdate)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
if (m_lastChangesRequireFullUpdate) {
SET_NEXT_STATE(ScopeState_TraceVoltsDivRequest)
}
else {
SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate)
}
}
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else if (m_commHandlerState == ScopeState_ChannelActiveStateUpdate+1) {
// Get response data
if (m_socket->canReadFrame()) {
PAT_WATCHDOG_TIMER
setTickerMessage(i18n("Updating [Set channel %1 activity status]").arg(m_currentOpChannel));
// Set channel active, step 2
TQString result;
ds >> result;
m_socket->clearFrameTail();
if (result == "ACK") {
m_currentOpChannel = getNextActiveChannel(m_currentOpChannel, m_channelActive, m_maxNumberOfTraces);
if (m_currentOpChannel > 0) {
SET_NEXT_STATE(ScopeState_ChannelActiveStateUpdate)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
if (m_lastChangesRequireFullUpdate) {
SET_NEXT_STATE(ScopeState_TraceVoltsDivRequest)
}
else {
SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate)
}
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
COMMUNICATIONS_FAILED
}
}
else {
if (!m_updateTimeoutTimer->isActive()) {
UPDATEDISPLAY_TIMEOUT
}
}
}
else if (m_commHandlerState == ScopeState_TraceVoltsDivUpdate) {
if (m_voltsDivSet[m_currentOpChannel]) {
// Set volts per division, step 1
ds << TQString("SETVOLTSDIV");
ds << m_currentOpChannel;
ds << m_voltsDiv[m_currentOpChannel];
m_socket->writeEndOfFrame();
m_voltsDivSet[m_currentOpChannel] = false;
SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate+1)
}
else {
m_currentOpChannel = getNextActiveChannel(m_currentOpChannel, m_channelActive, m_maxNumberOfTraces);
if (m_currentOpChannel > 0) {
SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate)
}
else {
SET_NEXT_STATE(ScopeState_TriggerLevelUpdate)
}
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else if (m_commHandlerState == ScopeState_TraceVoltsDivUpdate+1) {
// Get response data
if (m_socket->canReadFrame()) {
PAT_WATCHDOG_TIMER
setTickerMessage(i18n("Updating [Set volts/div for channel %1]").arg(m_currentOpChannel));
// Set volts per division, step 2
TQString result;
ds >> result;
m_socket->clearFrameTail();
if (result == "ACK") {
m_currentOpChannel = getNextActiveChannel(m_currentOpChannel, m_channelActive, m_maxNumberOfTraces);
if (m_currentOpChannel > 0) {
SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate)
}
else {
SET_NEXT_STATE(ScopeState_TriggerLevelUpdate)
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
COMMUNICATIONS_FAILED
}
}
else {
if (!m_updateTimeoutTimer->isActive()) {
UPDATEDISPLAY_TIMEOUT
}
}
}
else if (m_commHandlerState == ScopeState_TriggerLevelUpdate) {
if (m_voltsDivSet[m_currentOpChannel]) {
// Set trigger level, step 1
ds << TQString("SETTRIGGERLEVEL");
ds << m_triggerLevel;
m_socket->writeEndOfFrame();
m_triggerLevelSet = false;
SET_NEXT_STATE(ScopeState_TriggerLevelUpdate+1)
}
else {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
SET_NEXT_STATE(ScopeState_TraceRequest)
}
EXEC_NEXT_STATE_IMMEDIATELY
}
else if (m_commHandlerState == ScopeState_TriggerLevelUpdate+1) {
// Get response data
if (m_socket->canReadFrame()) {
PAT_WATCHDOG_TIMER
setTickerMessage(i18n("Updating [Set trigger level]"));
// Set trigger level, step 2
TQString result;
ds >> result;
m_socket->clearFrameTail();
if (result == "ACK") {
m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces);
SET_NEXT_STATE(ScopeState_TraceRequest)
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
COMMUNICATIONS_FAILED
}
}
else {
if (!m_updateTimeoutTimer->isActive()) {
UPDATEDISPLAY_TIMEOUT
}
}
}
else if (m_commHandlerState == ScopeState_ExternalCommandRequest) {
// Execute pending command
m_commHandlerMode = 2;
@ -892,12 +1199,18 @@ void ScopePart::postProcessTrace() {
void ScopePart::startDAQ() {
stopTraceUpdate = false;
if (m_socket) m_socket->clearIncomingData();
EXEC_NEXT_STATE_IMMEDIATELY
}
void ScopePart::stopDAQ() {
if (m_commHandlerMode < 2) {
stopTraceUpdate = true;
for (int i=0; i<=MAXTRACES;i++) {
m_channelActiveSet[i] = false;
m_voltsDivSet[i] = false;
}
m_triggerLevelSet = false;
m_commHandlerMode = 1;
m_commHandlerCommandState = 3;
mainEventLoop();
@ -976,11 +1289,9 @@ void ScopePart::recallWaveforms() {
m_triggerLevel = 0;
updateGraticule();
postProcessTrace();
// HACK
// Force resize of parent frame
emit(resizeToHintRequested());
m_traceWidget->repaint(false);
m_base->traceZoomWidget->repaint(false);
updateTraceControlWidgets();
}
else {
KMessageBox::error(0, i18n("<qt>The selected waveform file version does not match this client</qt>"), i18n("Invalid File"));
@ -1010,26 +1321,28 @@ void ScopePart::updateGraticule() {
m_base->traceZoomWidget->setNumberOfHorizontalDivisions(m_hdivs);
m_base->traceZoomWidget->setNumberOfVerticalDivisions(m_vdivs);
if ((m_triggerChannel > 0) && (m_triggerChannel <= m_maxNumberOfTraces)) {
TraceNumberList activeTraces;
activeTraces.append(m_triggerChannel-1);
m_traceWidget->setCursorActiveTraceList(0, activeTraces);
m_traceWidget->setCursorPosition(0, (50.0-((m_triggerLevel*100.0)/(m_voltsDiv[m_triggerChannel]*m_vdivs))));
m_traceWidget->setCursorEnabled(0, true);
}
else {
m_traceWidget->setCursorEnabled(0, false);
if (!m_triggerLevelSet) {
if ((m_triggerChannel > 0) && (m_triggerChannel <= m_maxNumberOfTraces)) {
TraceNumberList activeTraces;
activeTraces.append(m_triggerChannel-1);
m_traceWidget->setCursorActiveTraceList(0, activeTraces);
m_traceWidget->setCursorPosition(0, (50.0-((m_triggerLevel*100.0)/(m_voltsDiv[m_triggerChannel]*m_vdivs))));
m_traceWidget->setCursorEnabled(0, true);
}
else {
m_traceWidget->setCursorEnabled(0, false);
}
}
m_traceWidget->setTraceColor(0, TQColor(255, 255, 255));
m_traceWidget->setTraceColor(1, TQColor(128, 255, 128));
m_traceWidget->setTraceColor(2, TQColor(255, 255, 128));
m_traceWidget->setTraceColor(3, TQColor(128, 128, 255));
if (m_maxNumberOfTraces > 0) m_traceWidget->setTraceColor(0, TQColor(255, 255, 255));
if (m_maxNumberOfTraces > 1) m_traceWidget->setTraceColor(1, TQColor(128, 255, 128));
if (m_maxNumberOfTraces > 2) m_traceWidget->setTraceColor(2, TQColor(255, 255, 128));
if (m_maxNumberOfTraces > 3) m_traceWidget->setTraceColor(3, TQColor(128, 128, 255));
m_base->traceZoomWidget->setTraceColor(0, TQColor(255, 255, 255));
m_base->traceZoomWidget->setTraceColor(1, TQColor(128, 255, 128));
m_base->traceZoomWidget->setTraceColor(2, TQColor(255, 255, 128));
m_base->traceZoomWidget->setTraceColor(3, TQColor(128, 128, 255));
if (m_maxNumberOfTraces > 0) m_base->traceZoomWidget->setTraceColor(0, TQColor(255, 255, 255));
if (m_maxNumberOfTraces > 1) m_base->traceZoomWidget->setTraceColor(1, TQColor(128, 255, 128));
if (m_maxNumberOfTraces > 2) m_base->traceZoomWidget->setTraceColor(2, TQColor(255, 255, 128));
if (m_maxNumberOfTraces > 3) m_base->traceZoomWidget->setTraceColor(3, TQColor(128, 128, 255));
for (int traceno=1; traceno<=m_maxNumberOfTraces; traceno++) {
m_traceWidget->setTraceEnabled(traceno-1, m_channelActive[traceno]);
@ -1046,22 +1359,92 @@ void ScopePart::updateGraticule() {
m_base->traceZoomWidget->setNumberOfSamples(traceno-1, m_samplesInTrace[traceno]);
m_traceWidget->setDisplayLimits(traceno-1, TQRectF(0.0, (m_voltsDiv[traceno]*m_vdivs)/2.0, (m_secsDiv[traceno]*m_hdivs), (m_voltsDiv[traceno]*m_vdivs)/-2.0));
if (m_traceControlWidgetList[traceno-1]) {
m_traceControlWidgetList[traceno-1]->setSelectedVoltsPerDiv(m_voltsDiv[traceno]);
m_traceControlWidgetList[traceno-1]->setTraceEnabled(m_channelActive[traceno]);
}
}
updateZoomWidgetLimits(m_traceWidget->zoomBox());
}
void ScopePart::updateTraceControlWidgets() {
// Add or remove trace control widgets as needed...
int i;
for (i=0; i<m_maxNumberOfTraces;i++) {
if (!m_traceControlWidgetList[i]) {
m_traceControlWidgetList[i] = new TraceControlWidget(m_base->traceControlLayoutWidget);
connect(m_traceControlWidgetList[i], SIGNAL(enableChanged(bool)), this, SLOT(traceControlEnableChanged(bool)));
connect(m_traceControlWidgetList[i], SIGNAL(voltsPerDivChanged(double)), this, SLOT(traceControlVDivChanged(double)));
m_traceControlWidgetGrid->addMultiCellWidget(m_traceControlWidgetList[i], i, i, 0, 0);
m_traceControlWidgetList[i]->setTraceName(i18n("Channel %1").arg(i+1));
m_traceControlWidgetList[i]->show();
}
}
for (i=m_maxNumberOfTraces; i<MAXTRACES;i++) {
if (m_traceControlWidgetList[i]) {
m_traceControlWidgetGrid->remove(m_traceControlWidgetList[i]);
delete m_traceControlWidgetList[i];
}
}
}
void ScopePart::traceControlEnableChanged(bool enabled) {
int i;
int channel = -1;
const TraceControlWidget* widget = dynamic_cast<const TraceControlWidget*>(sender());
if (widget) {
for (i=0; i<MAXTRACES;i++) {
if (m_traceControlWidgetList[i] == widget) {
channel = i;
break;
}
}
if ((channel >= 0) && (channel <=MAXTRACES)) {
m_channelActive[channel+1] = enabled;
m_channelActiveSet[channel+1] = true;
}
}
updateGraticule();
m_traceWidget->repaint(false);
m_base->traceZoomWidget->repaint(false);
updateTraceControlWidgets();
}
void ScopePart::traceControlVDivChanged(double vdiv) {
int i;
int channel = -1;
const TraceControlWidget* widget = dynamic_cast<const TraceControlWidget*>(sender());
if (widget) {
for (i=0; i<MAXTRACES;i++) {
if (m_traceControlWidgetList[i] == widget) {
channel = i;
break;
}
}
if ((channel >= 0) && (channel <=MAXTRACES)) {
m_voltsDiv[channel+1] = vdiv;
m_voltsDivSet[channel+1] = true;
}
}
// // Also update controls
// m_base->saRefLevel->blockSignals(true);
// m_base->saRefLevel->setFloatValue(m_voltsDiv);
// m_base->saRefLevel->blockSignals(false);
updateGraticule();
m_traceWidget->repaint(false);
m_base->traceZoomWidget->repaint(false);
updateTraceControlWidgets();
}
void ScopePart::saRefLevelChanged(double newval) {
// if (m_commHandlerMode < 2) {
// m_voltsDiv = newval;
// m_commHandlerMode = 1;
// m_commHandlerCommandState = 1;
// mainEventLoop();
// }
void ScopePart::cursorLevelChanged(uint cursor, double level) {
if (cursor == 0) {
// Trigger level changed
m_triggerLevel = (((50.0-level)*(m_voltsDiv[m_triggerChannel]*m_vdivs))/100.0);
m_triggerLevelSet = true;
updateGraticule();
m_traceWidget->repaint(false);
m_base->traceZoomWidget->repaint(false);
updateTraceControlWidgets();
}
}
KAboutData* ScopePart::createAboutData() {

@ -20,10 +20,44 @@ class TQSocket;
class TQTimer;
class TQMutex;
class TQRectF;
class TQGridLayout;
class TQCheckBox;
class TQGroupBox;
class ScopeBase;
namespace RemoteLab
{
class TraceControlWidget : public TQWidget
{
Q_OBJECT
public:
TraceControlWidget(TQWidget *parent=0, const char *name=0);
~TraceControlWidget();
public:
void setVoltsPerDivList(TQDoubleList list);
void setSelectedVoltsPerDiv(double vdiv);
void setTraceEnabled(bool enabled);
void setTraceName(TQString name);
signals:
void enableChanged(bool enabled);
void voltsPerDivChanged(double vdiv);
private slots:
void enableClicked();
void vdivChanged(int index);
private:
TQGroupBox* m_groupBox;
TQGridLayout* m_primaryLayout;
TQComboBox* m_voltsDivComboBox;
TQCheckBox* m_channelEnabledCheckBox;
TQDoubleList m_voltsDivList;
};
class ScopePart : public KParts::RemoteInstrumentPart
{
Q_OBJECT
@ -51,13 +85,17 @@ namespace RemoteLab
void mainEventLoop();
void startDAQ();
void stopDAQ();
void updateTraceControlWidgets();
void traceControlEnableChanged(bool enabled);
void traceControlVDivChanged(double vdiv);
void cursorLevelChanged(uint cursor, double level);
void saveWaveforms();
void recallWaveforms();
virtual void postProcessTrace();
void saRefLevelChanged(double);
private:
TraceWidget* m_traceWidget;
TQGridLayout* m_traceControlWidgetGrid;
int m_commHandlerState;
int m_commHandlerMode;
int m_commHandlerCommandState;
@ -77,6 +115,11 @@ namespace RemoteLab
bool m_channelActive[MAXTRACES+1];
double m_voltsDiv[MAXTRACES+1];
double m_secsDiv[MAXTRACES+1];
TraceControlWidget* m_traceControlWidgetList[MAXTRACES];
bool m_triggerLevelSet;
bool m_voltsDivSet[MAXTRACES+1];
bool m_channelActiveSet[MAXTRACES+1];
bool m_lastChangesRequireFullUpdate;
ScopeBase* m_base;
TQMutex* m_instrumentMutex;
bool stopTraceUpdate;

@ -372,6 +372,7 @@ void CursorData::movePosOneTick() {
if (position < 0.0) position = 0.0;
if (position > 100.0) position = 100.0;
emit(positionChanged(position));
parentWidget->updateCursorText();
parentWidget->m_graticuleWidget->updateGraticule();
parentWidget->m_graticuleWidget->repaint(false);
@ -394,6 +395,7 @@ void CursorData::moveNegOneTick() {
if (position < 0.0) position = 0.0;
if (position > 100.0) position = 100.0;
emit(positionChanged(position));
parentWidget->updateCursorText();
parentWidget->m_graticuleWidget->updateGraticule();
parentWidget->m_graticuleWidget->repaint(false);
@ -416,6 +418,7 @@ void CursorData::movePosMultiTicks() {
if (position < 0.0) position = 0.0;
if (position > 100.0) position = 100.0;
emit(positionChanged(position));
parentWidget->updateCursorText();
parentWidget->m_graticuleWidget->updateGraticule();
parentWidget->m_graticuleWidget->repaint(false);
@ -438,6 +441,7 @@ void CursorData::moveNegMultiTicks() {
if (position < 0.0) position = 0.0;
if (position > 100.0) position = 100.0;
emit(positionChanged(position));
parentWidget->updateCursorText();
parentWidget->m_graticuleWidget->updateGraticule();
parentWidget->m_graticuleWidget->repaint(false);
@ -1528,8 +1532,24 @@ void TraceWidget::processChangedOffset(double offset) {
}
}
void TraceWidget::processChangedCusorPosition(double position) {
// Find the sending cursor number
const CursorData* sendingCursor = dynamic_cast<const CursorData*>(sender());
if (sendingCursor) {
int cursornumber = -1;
for (uint cursor=0;cursor<m_cursorArray.count();cursor++) {
if (sendingCursor == m_cursorArray[cursor]) {
cursornumber = cursor;
}
}
if (cursornumber >= 0) {
emit(cursorDragged(cursornumber, position));
}
}
}
void TraceWidget::processChangedCursor(uint cursorNumber, double newPosition) {
emit(cursorPositionChanged(cursorNumber, newPosition));
emit(cursorDragged(cursorNumber, newPosition));
}
void TraceWidget::resizeTraceArray(uint newsize) {
@ -1573,6 +1593,7 @@ void TraceWidget::resizeCursorArray(uint newsize) {
m_cursorArray.resize(newsize);
for (uint i=oldcount;i<newsize;i++) {
m_cursorArray[i] = new CursorData(this, this);
connect(m_cursorArray[i], SIGNAL(positionChanged(double)), this, SLOT(processChangedCusorPosition(double)));
if (m_cursorArray[i]->paramLabel) {
m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->paramLabel, i*2, i*2, 0, 3);
m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->multiIncrBtn, (i*2)+1, (i*2)+1, 0, 0);

@ -109,6 +109,9 @@ class CursorData : public TQObject
protected:
virtual bool eventFilter(TQObject *o, TQEvent *e);
signals:
void positionChanged(double newPosition);
private:
TQColor color;
TQColor highlightColor;
@ -237,11 +240,13 @@ class TraceWidget : public TQWidget
void updateCursorText();
void processChangedOffset(double offset);
void processChangedCursor(uint cursorNumber, double newPosition);
void processChangedCusorPosition(double position);
signals:
void zoomBoxChanged(const TQRectF&);
void offsetChanged(uint traceNumber, double offset);
void cursorPositionChanged(uint cursorNumber, double newPosition);
void cursorDragged(uint cursorNumber, double newPosition);
private:
void resizeTraceArray(uint newsize);

@ -33,6 +33,13 @@
// =============================================================================
typedef TQValueList<float> TQFloatList;
typedef TQValueList<double> TQDoubleList;
typedef TQValueList<TQ_INT32> TQInt32List;
typedef TQValueList<TQ_INT16> TQInt16List;
// =============================================================================
namespace KParts
{
class RemoteInstrumentPartPrivate;

@ -313,7 +313,7 @@ void GPIBSocket::commandLoop() {
else if (m_instrumentCommand == "SETVOLTSDIV") { // Want to change volts per division
TQ_INT32 value1;
ds >> value1;
float value2;
double value2;
ds >> value2;
if (scope_set_volts_div(value1, value2, m_serverParent->m_scopeType.ascii(), m_serverParent->m_scopeDeviceSocket) == 0) {
ds << TQString("ACK");
@ -507,6 +507,34 @@ void GPIBSocket::commandLoop() {
writeEndOfFrame();
}
}
else if (m_instrumentCommand == "GETPERMITTEDVDIVS") { // Want to get permitted volts/div settings
double attenuation_mult;
double* permitted_array;
int permitted_count;
TQ_INT32 value;
ds >> value;
if (scope_get_probe_attenuation_multiplier(&attenuation_mult, value, m_serverParent->m_scopeType.ascii(), m_serverParent->m_scopeDeviceSocket) == 0) {
if (scope_get_permitted_volts_div_settings_at_1x(&permitted_count, &permitted_array, m_serverParent->m_scopeType.ascii(), m_serverParent->m_scopeDeviceSocket) == 0) {
long i;
TQDoubleList permittedValues;
for (i=0; i<permitted_count; i++) {
permittedValues.append(permitted_array[i]/attenuation_mult);
}
free(permitted_array);
ds << TQString("ACK");
ds << permittedValues;
writeEndOfFrame();
}
else {
ds << TQString("NCK");
writeEndOfFrame();
}
}
else {
ds << TQString("NCK");
writeEndOfFrame();
}
}
else {
printf("[WARNING] Received unknown command %s from host %s\n\r", m_instrumentCommand.ascii(), m_remoteHost.ascii()); fflush(stdout);
}

@ -273,9 +273,9 @@ int scope_set_timebase(float desired_timebase,const char * scopeType, int gpibDe
}
}
int scope_set_volts_div(int desired_channel, float desired_volts,const char * scopeType, int gpibDevice) {
int scope_set_volts_div(int desired_channel, double desired_volts, const char * scopeType, int gpibDevice) {
if ((strcmp("HP54600OS", scopeType) == 0) || (strcmp("TDS744AOS", scopeType) == 0)) {
printf("[INFO] Setting scope volts/div on channel %d to %f\n\r", desired_channel, desired_volts/8);
printf("[INFO] Setting scope volts/div on channel %d to %E\n\r", desired_channel, desired_volts);
if (strcmp("HP54600OS", scopeType) == 0) {
sprintf(falpha, "CHAN%d:RANG %E", desired_channel, desired_volts);
#ifdef ENABLE_EXTRA_DEBUGGING
@ -289,7 +289,7 @@ int scope_set_volts_div(int desired_channel, float desired_volts,const char * sc
}
}
else if (strcmp("TDS744AOS", scopeType) == 0) {
sprintf(falpha, "CH%d:SCALE %f", desired_channel, desired_volts/8);
sprintf(falpha, "CH%d:SCALE %E", desired_channel, desired_volts);
#ifdef ENABLE_EXTRA_DEBUGGING
printf("[DEBG] Writing: %s\n\r", falpha);
#endif
@ -387,6 +387,7 @@ int scope_set_channel_state(int desired_channel, int status,const char * scopeTy
printf("[DEBG] Writing: %s\n\r", falpha);
#endif
if (gpib_write(gpibDevice, falpha) == 0) {
usleep(2*1000000); // The scope is slow to respond, and also blind to commands during the update window! [RAJA TESTME]
return 0;
}
else {
@ -1118,4 +1119,83 @@ int scope_get_channel_sample_count(unsigned long * retval, int desired_channel,
else {
return -1;
}
}
int scope_get_probe_attenuation_multiplier(double * retval, int desired_channel, const char * scopeType, int gpibDevice) {
char floatstring[1024];
long ai;
int max_num_bytes = 0;
if (strcmp("HP54600OS", scopeType) == 0) {
// FIXME
// Not supported (yet)
return -1;
}
else if (strcmp("TDS744AOS", scopeType) == 0) {
// Send request
printf("[INFO] Getting trigger level for channel %d\n\r", desired_channel);
sprintf(falpha,"CH%d:PROBE?", desired_channel);
#ifdef ENABLE_EXTRA_DEBUGGING
printf("[DEBG] Writing: %s\n\r", falpha);
#endif
if (gpib_write(gpibDevice, falpha) == 0) {
max_num_bytes = 24; // Request more bytes than are possible to ensure no bytes are left behind
}
else {
return 2;
}
// Read response
#ifdef ENABLE_EXTRA_DEBUGGING
printf("[DEBG] Trying to read %i bytes from GPIB device...\n", max_num_bytes);
#endif
ai = gpib_read_array(gpibDevice, max_num_bytes, floatstring);
if (ai == -1) {
return 1;
}
else {
floatstring[ai]=0;
*retval = atof(floatstring);
}
#ifdef ENABLE_EXTRA_DEBUGGING
printf("[DEBG] Read %li bytes from GPIB device\n", ai);
#endif
return 0;
}
else {
return -1;
}
}
int scope_get_permitted_volts_div_settings_at_1x(int * number_of_values, double ** retarray, const char * scopeType, int gpibDevice) {
if (strcmp("HP54600OS", scopeType) == 0) {
// FIXME
// Not supported (yet)
return -1;
}
else if (strcmp("TDS744AOS", scopeType) == 0) {
*number_of_values = 13;
double* values = (double*)malloc(sizeof(double)*(*number_of_values));
values[0] = 1e-3;
values[1] = 2e-3;
values[2] = 5e-3;
values[3] = 1e-2;
values[4] = 2e-2;
values[5] = 5e-2;
values[6] = 1e-1;
values[7] = 2e-1;
values[8] = 5e-1;
values[9] = 1e0;
values[10] = 2e0;
values[11] = 5e0;
values[12] = 1e1;
*retarray = values;
return 0;
}
else {
return -1;
}
}

@ -33,7 +33,7 @@ int scope_get_screenshot(const char * scopeType, int gpibDevice);
int scope_get_screenshot_stage2(const char * scopeType, int gpibDevice);
int scope_perform_initial_setup(const char * scopeType, int gpibDevice);
int scope_set_timebase(float desired_timebase,const char * scopeType, int gpibDevice);
int scope_set_volts_div(int desired_channel, float desired_volts,const char * scopeType, int gpibDevice);
int scope_set_volts_div(int desired_channel, double desired_volts, const char * scopeType, int gpibDevice);
int scope_set_acquisition(int status,const char * scopeType, int gpibDevice);
int scope_set_channel_state(int desired_channel, int status,const char * scopeType, int gpibDevice);
int scope_get_channel_state(int * retval, int desired_channel, const char * scopeType, int gpibDevice);
@ -48,4 +48,6 @@ int scope_get_trigger_channel(int * retval, const char * scopeType, int gpibDevi
int scope_get_trigger_level(double * retval, const char * scopeType, int gpibDevice);
int scope_get_channel_volts_div(double * retval, int desired_channel, const char * scopeType, int gpibDevice);
int scope_get_channel_seconds_div(double * retval, int desired_channel, const char * scopeType, int gpibDevice);
int scope_get_channel_sample_count(unsigned long * retval, int desired_channel, const char * scopeType, int gpibDevice);
int scope_get_channel_sample_count(unsigned long * retval, int desired_channel, const char * scopeType, int gpibDevice);
int scope_get_probe_attenuation_multiplier(double * retval, int desired_channel, const char * scopeType, int gpibDevice);
int scope_get_permitted_volts_div_settings_at_1x(int * number_of_values, double ** retarray, const char * scopeType, int gpibDevice);
Loading…
Cancel
Save