diff options
Diffstat (limited to 'clients/tde/src/part')
-rw-r--r-- | clients/tde/src/part/scope/layout.ui | 56 | ||||
-rw-r--r-- | clients/tde/src/part/scope/part.cpp | 505 | ||||
-rw-r--r-- | clients/tde/src/part/scope/part.h | 45 |
3 files changed, 492 insertions, 114 deletions
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 @@ </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> 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 <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(); @@ -574,6 +669,54 @@ void ScopePart::mainEventLoop() { } 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) } EXEC_NEXT_STATE_IMMEDIATELY @@ -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() { 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; |