From 23eadbf9246280ce6473a4fe4d3605cd730eb8c8 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 18 Jul 2012 16:33:39 -0500 Subject: [PATCH] Add channel controls to scope --- clients/tde/src/app/views/instrumentview.cpp | 21 +- clients/tde/src/app/views/instrumentview.h | 1 + clients/tde/src/part/scope/layout.ui | 56 +- clients/tde/src/part/scope/part.cpp | 505 +++++++++++++++--- clients/tde/src/part/scope/part.h | 45 +- clients/tde/src/widgets/tracewidget.cpp | 23 +- clients/tde/src/widgets/tracewidget.h | 5 + lib/libtqtrla/src/tqtrla.h | 7 + servers/gpib_server_lin/src/gpib_conn.cpp | 30 +- .../gpib_server_lin/src/scope_functions.cpp | 86 ++- servers/gpib_server_lin/src/scope_functions.h | 6 +- 11 files changed, 662 insertions(+), 123 deletions(-) diff --git a/clients/tde/src/app/views/instrumentview.cpp b/clients/tde/src/app/views/instrumentview.cpp index 429f670..494b947 100644 --- a/clients/tde/src/app/views/instrumentview.cpp +++ b/clients/tde/src/app/views/instrumentview.cpp @@ -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()); } } } diff --git a/clients/tde/src/app/views/instrumentview.h b/clients/tde/src/app/views/instrumentview.h index f51fab8..ed592dd 100644 --- a/clients/tde/src/app/views/instrumentview.h +++ b/clients/tde/src/app/views/instrumentview.h @@ -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); diff --git a/clients/tde/src/part/scope/layout.ui b/clients/tde/src/part/scope/layout.ui index 9390e82..ee3bb81 100644 --- a/clients/tde/src/part/scope/layout.ui +++ b/clients/tde/src/part/scope/layout.ui @@ -98,63 +98,15 @@ - groupOscilloscopeTraceControls + groupOscilloscopeCaptureControls - Receiver Controls + Capture Controls - + - unnamed - - - Reference Power Level: - - - PlainText - - - - - saRefLevel - - - true - - - - 3 - 0 - 0 - 0 - - - - - 80 - 0 - - - - 128 - - - -128 - - - 0 - - - - - unnamed - - - dBm - - - PlainText + traceControlLayoutWidget diff --git a/clients/tde/src/part/scope/part.cpp b/clients/tde/src/part/scope/part.cpp index 9909e65..17c137d 100644 --- a/clients/tde/src/part/scope/part.cpp +++ b/clients/tde/src/part/scope/part.cpp @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -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 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;icount();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("The selected waveform file version does not match this client"), 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; itraceControlLayoutWidget); + 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; iremove(m_traceControlWidgetList[i]); + delete m_traceControlWidgetList[i]; + } + } +} + +void ScopePart::traceControlEnableChanged(bool enabled) { + int i; + int channel = -1; + const TraceControlWidget* widget = dynamic_cast(sender()); + if (widget) { + for (i=0; i= 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(sender()); + if (widget) { + for (i=0; i= 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() { diff --git a/clients/tde/src/part/scope/part.h b/clients/tde/src/part/scope/part.h index 1e342da..24e2c84 100644 --- a/clients/tde/src/part/scope/part.h +++ b/clients/tde/src/part/scope/part.h @@ -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; diff --git a/clients/tde/src/widgets/tracewidget.cpp b/clients/tde/src/widgets/tracewidget.cpp index 6375a13..1ee9721 100644 --- a/clients/tde/src/widgets/tracewidget.cpp +++ b/clients/tde/src/widgets/tracewidget.cpp @@ -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(sender()); + if (sendingCursor) { + int cursornumber = -1; + for (uint cursor=0;cursor= 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;iparamLabel) { 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); diff --git a/clients/tde/src/widgets/tracewidget.h b/clients/tde/src/widgets/tracewidget.h index 7ca1e24..fec91e3 100644 --- a/clients/tde/src/widgets/tracewidget.h +++ b/clients/tde/src/widgets/tracewidget.h @@ -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); diff --git a/lib/libtqtrla/src/tqtrla.h b/lib/libtqtrla/src/tqtrla.h index 129eac9..be105b8 100644 --- a/lib/libtqtrla/src/tqtrla.h +++ b/lib/libtqtrla/src/tqtrla.h @@ -33,6 +33,13 @@ // ============================================================================= +typedef TQValueList TQFloatList; +typedef TQValueList TQDoubleList; +typedef TQValueList TQInt32List; +typedef TQValueList TQInt16List; + +// ============================================================================= + namespace KParts { class RemoteInstrumentPartPrivate; diff --git a/servers/gpib_server_lin/src/gpib_conn.cpp b/servers/gpib_server_lin/src/gpib_conn.cpp index b46f469..dc081a3 100644 --- a/servers/gpib_server_lin/src/gpib_conn.cpp +++ b/servers/gpib_server_lin/src/gpib_conn.cpp @@ -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