diff options
-rw-r--r-- | clients/tde/configure.in | 1 | ||||
-rw-r--r-- | clients/tde/src/part/Makefile.am | 2 | ||||
-rw-r--r-- | clients/tde/src/part/commanalyzer/debug.h | 36 | ||||
-rw-r--r-- | clients/tde/src/part/commanalyzer/part.cpp | 1 | ||||
-rw-r--r-- | clients/tde/src/part/scope/Makefile.am | 10 | ||||
-rw-r--r-- | clients/tde/src/part/scope/layout.ui | 178 | ||||
-rw-r--r-- | clients/tde/src/part/scope/part.cpp | 769 | ||||
-rw-r--r-- | clients/tde/src/part/scope/part.h | 77 |
8 files changed, 1036 insertions, 38 deletions
diff --git a/clients/tde/configure.in b/clients/tde/configure.in index 3753714..58e7262 100644 --- a/clients/tde/configure.in +++ b/clients/tde/configure.in @@ -89,6 +89,7 @@ AC_CONFIG_FILES([ src/part/Makefile ]) AC_CONFIG_FILES([ src/part/commanalyzer/Makefile ]) AC_CONFIG_FILES([ src/part/fpgaprogram/Makefile ]) AC_CONFIG_FILES([ src/part/fpgaview/Makefile ]) +AC_CONFIG_FILES([ src/part/scope/Makefile ]) AC_CONFIG_FILES([ src/widgets/Makefile ]) AC_OUTPUT # Check if KDE_SET_PREFIX was called, and --prefix was passed to configure diff --git a/clients/tde/src/part/Makefile.am b/clients/tde/src/part/Makefile.am index b2962ff..cdb75aa 100644 --- a/clients/tde/src/part/Makefile.am +++ b/clients/tde/src/part/Makefile.am @@ -1 +1 @@ -SUBDIRS = commanalyzer fpgaview fpgaprogram +SUBDIRS = scope commanalyzer fpgaview fpgaprogram diff --git a/clients/tde/src/part/commanalyzer/debug.h b/clients/tde/src/part/commanalyzer/debug.h deleted file mode 100644 index e5e680b..0000000 --- a/clients/tde/src/part/commanalyzer/debug.h +++ /dev/null @@ -1,36 +0,0 @@ -//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4 -//Copyright: See COPYING file that comes with this distribution - -#ifndef DEBUG_H -#define DEBUG_H - -/** Fancy debug header - * @author Max Howell - * - * Define DEBUG_PREFIX as a string before you include this to insert a fancy debug prefix - * Debug::debug(), can be used as debug() and is just kdDebug() - * use Debug::indent() and Debug::unindent() - */ - -#include <kdebug.h> - -#ifdef NDEBUG -static inline kndbgstream debug() { return kndbgstream(); } -#else -static inline kdbgstream debug() -{ - return kdbgstream( - #ifdef DEBUG_PREFIX - "[" DEBUG_PREFIX "] ", - #endif - 0, 0 ); -} -#endif - -#define error kdError -#define fatal kdFatal -#define warning kdWarning - -#define DEBUG_ANNOUNCE debug() << ">> " << __PRETTY_FUNCTION__ << endl; - -#endif diff --git a/clients/tde/src/part/commanalyzer/part.cpp b/clients/tde/src/part/commanalyzer/part.cpp index a5c3e4d..8b92ea4 100644 --- a/clients/tde/src/part/commanalyzer/part.cpp +++ b/clients/tde/src/part/commanalyzer/part.cpp @@ -1,7 +1,6 @@ //Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (C) 2012 //Copyright: See COPYING file that comes with this distribution -#include "debug.h" #include "define.h" #include "part.h" diff --git a/clients/tde/src/part/scope/Makefile.am b/clients/tde/src/part/scope/Makefile.am new file mode 100644 index 0000000..b2b9c34 --- /dev/null +++ b/clients/tde/src/part/scope/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = $(all_includes) -I$(top_srcdir)/src -I$(top_srcdir)/src/widgets $(KDE_INCLUDES)/tde +KDE_CXXFLAGS = $(USE_EXCEPTIONS) +METASOURCES = AUTO + +#Part +kde_module_LTLIBRARIES = libremotelab_scope.la +libremotelab_scope_la_LIBADD = ../../widgets/libtracewidget.la ../../widgets/libfloatspinbox.la $(LIB_KFILE) $(LIB_KPARTS) $(LIB_TDEUI) $(LIB_QT) +libremotelab_scope_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -ltdecore -ltdeui -lkio -ltdefx -ltdekrbsocket -ltqtrla +libremotelab_scope_la_SOURCES = \ + part.cpp layout.ui diff --git a/clients/tde/src/part/scope/layout.ui b/clients/tde/src/part/scope/layout.ui new file mode 100644 index 0000000..9b69b57 --- /dev/null +++ b/clients/tde/src/part/scope/layout.ui @@ -0,0 +1,178 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> + <class>ScopeBase</class> + <widget class="TQWidget"> + <property name="name"> + <cstring>ScopeBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>519</width> + <height>356</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQTabWidget" row="0" column="0"> + <property name="name"> + <cstring>TabWidget2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <widget class="TQWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Oscilloscope</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupOscilloscope</cstring> + </property> + <property name="title"> + <string>Oscilloscope</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupOscilloscopeView</cstring> + </property> + <property name="title"> + <string>Trace Viewer</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TraceWidget" row="0" column="0" colspan="1"> + <property name="name"> + <cstring>traceWidget</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>80</height> + </size> + </property> + </widget> + <widget class="TraceWidget" row="1" column="0" colspan="1"> + <property name="name"> + <cstring>traceZoomWidget</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>80</height> + </size> + </property> + </widget> + </grid> + </widget> + <widget class="TQGroupBox" row="0" column="1"> + <property name="name"> + <cstring>groupOscilloscopeTraceControls</cstring> + </property> + <property name="title"> + <string>Receiver Controls</string> + </property> + <grid> + <widget class="TQLabel" row="0" column="0" colspan="1"> + <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> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </grid> + </widget> + </widget> + </grid> + </widget> + <includes> + <include location="local" impldecl="in implementation">ScopeBase.ui.h</include> + </includes> + <includes> + <include location="local" impldecl="in implementation">tracewidget.h</include> + <include location="local" impldecl="in implementation">floatspinbox.h</include> + </includes> + <layoutdefaults spacing="3" margin="6"/> + <layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/clients/tde/src/part/scope/part.cpp b/clients/tde/src/part/scope/part.cpp new file mode 100644 index 0000000..4d27930 --- /dev/null +++ b/clients/tde/src/part/scope/part.cpp @@ -0,0 +1,769 @@ +//Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (C) 2012 +//Copyright: See COPYING file that comes with this distribution + +#include "define.h" +#include "part.h" + +#include <kaboutdata.h> //::createAboutData() +#include <kaction.h> +#include <klocale.h> +#include <kmessagebox.h> //::start() +#include <kparts/genericfactory.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <tqfile.h> //encodeName() +#include <tqtimer.h> +#include <tqvbox.h> +#include <tqsocket.h> +#include <tqmutex.h> +#include <tqeventloop.h> +#include <tqapplication.h> +#include <unistd.h> //access() +#include <stdint.h> +#include <cmath> + +#include "tracewidget.h" +#include "floatspinbox.h" +#include "layout.h" + +#define NETWORK_COMM_TIMEOUT_MS 15000 + +/* exception handling */ +struct exit_exception { + int c; + exit_exception(int c):c(c) { } +}; + +namespace RemoteLab { + +typedef KParts::GenericFactory<RemoteLab::ScopePart> Factory; +#define CLIENT_LIBRARY "libremotelab_scope" +K_EXPORT_COMPONENT_FACTORY( libremotelab_scope, RemoteLab::Factory ) + + +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), + m_base(0), stopTraceUpdate(false) +{ + // Initialize important base class variables + m_clientLibraryName = CLIENT_LIBRARY; + + // Initialize mutex + m_instrumentMutex = new TQMutex(false); + + // Initialize kpart + setInstance(Factory::instance()); + setWidget(new TQVBox(parentWidget, widgetName)); + + // Create timers + m_forcedUpdateTimer = new TQTimer(this); + connect(m_forcedUpdateTimer, SIGNAL(timeout()), this, SLOT(mainEventLoop())); + m_updateTimeoutTimer = new TQTimer(this); + connect(m_updateTimeoutTimer, SIGNAL(timeout()), this, SLOT(mainEventLoop())); + + // Create widgets + m_base = new ScopeBase(widget()); + m_traceWidget = m_base->traceWidget; + m_traceWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); + m_traceWidget->setTraceEnabled(0, true); + m_traceWidget->setTraceName(0, "Trace 1"); + m_traceWidget->setTraceHorizontalUnits(0, "Hz"); + m_traceWidget->setTraceVerticalUnits(0, "dBm"); + m_traceWidget->setNumberOfCursors(4); + m_traceWidget->setCursorOrientation(0, TQt::Horizontal); + m_traceWidget->setCursorOrientation(1, TQt::Horizontal); + m_traceWidget->setCursorOrientation(2, TQt::Vertical); + m_traceWidget->setCursorOrientation(3, TQt::Vertical); + m_traceWidget->setCursorEnabled(0, true); + m_traceWidget->setCursorEnabled(1, true); + m_traceWidget->setCursorEnabled(2, true); + m_traceWidget->setCursorEnabled(3, true); + m_traceWidget->setCursorName(0, "Cursor H1"); + m_traceWidget->setCursorName(1, "Cursor H2"); + m_traceWidget->setCursorName(2, "Cursor V1"); + m_traceWidget->setCursorName(3, "Cursor V2"); + m_traceWidget->setCursorPosition(0, 25); + m_traceWidget->setCursorPosition(1, 75); + m_traceWidget->setCursorPosition(2, 25); + m_traceWidget->setCursorPosition(3, 75); + m_traceWidget->setZoomBoxEnabled(true); + + m_base->traceZoomWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); + m_base->traceZoomWidget->setTraceEnabled(0, true, false); + m_base->traceZoomWidget->setTraceName(0, "Trace 1"); + m_base->traceZoomWidget->setTraceHorizontalUnits(0, "Hz"); + m_base->traceZoomWidget->setTraceVerticalUnits(0, "dBm"); + 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->saRefLevel, SIGNAL(floatValueChanged(double)), this, SLOT(saRefLevelChanged(double))); + + TQTimer::singleShot(0, this, TQT_SLOT(postInit())); +} + +ScopePart::~ScopePart() { + if (m_instrumentMutex->locked()) { + printf("[WARNING] Exiting when data transfer still in progress!\n\r"); fflush(stdout); + } + + disconnectFromServer(); + delete m_instrumentMutex; +} + +void ScopePart::postInit() { + setUsingFixedSize(false); +} + +bool ScopePart::openURL(const KURL &url) { + int ret; + m_connectionActiveAndValid = false; + ret = connectToServer(url.url()); + processLockouts(); + return (ret != 0); +} + +bool ScopePart::closeURL() { + disconnectFromServer(); + m_url = KURL(); + return true; +} + +void ScopePart::processLockouts() { + if (m_connectionActiveAndValid) { + m_base->setEnabled(true); + } + else { + m_base->setEnabled(false); + } +} + +void ScopePart::disconnectFromServerCallback() { + m_forcedUpdateTimer->stop(); + m_updateTimeoutTimer->stop(); + m_connectionActiveAndValid = false; +} + +void ScopePart::connectionFinishedCallback() { + connect(m_socket, SIGNAL(readyRead()), m_socket, SLOT(processPendingData())); + m_socket->processPendingData(); + connect(m_socket, SIGNAL(newDataReceived()), this, SLOT(mainEventLoop())); + m_tickerState = 0; + m_commHandlerState = 0; + m_commHandlerMode = 0; + m_socket->setDataTimeout(NETWORK_COMM_TIMEOUT_MS); + m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); + processLockouts(); + mainEventLoop(); + return; +} + +void ScopePart::connectionStatusChangedCallback() { + processLockouts(); +} + +void ScopePart::setTickerMessage(TQString message) { + m_connectionActiveAndValid = true; + TQString tickerChar; + switch (m_tickerState) { + case 0: + tickerChar = "-"; + break; + case 1: + tickerChar = "\\"; + break; + case 2: + tickerChar = "|"; + break; + case 3: + tickerChar = "/"; + break; + } + setStatusMessage(message + TQString("... %1").arg(tickerChar)); + m_tickerState++; + if (m_tickerState > 3) { + m_tickerState = 0; + } +} + +#define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \ + m_tickerState = 0; \ + m_commHandlerState = 2; \ + m_commHandlerMode = 0; \ + m_socket->clearIncomingData(); \ + setStatusMessage(i18n("Server ping timeout. Please verify the status of your network connection.")); \ + m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + m_instrumentMutex->unlock(); \ + return; + +#define COMMUNICATIONS_FAILED m_connectionActiveAndValid = false; \ + m_tickerState = 0; \ + m_commHandlerState = 2; \ + m_commHandlerMode = 0; \ + m_socket->clearIncomingData(); \ + setStatusMessage(i18n("Instrument communication failure. Please verify the status of your network connection.")); \ + m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + m_instrumentMutex->unlock(); \ + return; + +#define SET_WATCHDOG_TIMER if (!m_updateTimeoutTimer->isActive()) m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); +#define PAT_WATCHDOG_TIMER m_updateTimeoutTimer->stop(); m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + setTickerMessage(i18n("Connected")); + +#define SET_NEXT_STATE(x) if (m_commHandlerMode == 0) { \ + m_commHandlerState = x; \ + } \ + else { \ + m_commHandlerState = 255; \ + } + +#define EXEC_NEXT_STATE_IMMEDIATELY m_forcedUpdateTimer->start(0, TRUE); + +void ScopePart::mainEventLoop() { + TQDataStream ds(m_socket); + ds.setPrintableData(true); + + if (!m_instrumentMutex->tryLock()) { + EXEC_NEXT_STATE_IMMEDIATELY + return; + } + + if (m_socket) { + if ((m_commHandlerMode == 0) || (m_commHandlerMode == 1)) { + if (m_commHandlerState == 0) { + // Request scope access + ds << TQString("OSCILLOSCOPE"); + m_socket->writeEndOfFrame(); + + m_commHandlerState = 1; + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 1) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get command status + TQString result; + ds >> result; + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(2) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 2) { + // Set spectrum analyzer mode + ds << TQString("SETMODESPECTRUMANALYZER"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(3) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 3) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get command status + TQString result; + ds >> result; + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(4) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 4) { + // Get number of samples in trace, step 1 + ds << TQString("GETTRACESAMPLECOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(5) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 5) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get number of samples in trace, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_samplesInTrace; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(6) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 6) { + // Get number of horizontal divisions, step 1 + ds << TQString("GETHORIZONTALDIVCOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(7) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 7) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get number of horizontal divisions, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_hdivs; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(8) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 8) { + // Get number of vertical divisions, step 1 + ds << TQString("GETVERTICALDIVCOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(9) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 9) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get number of vertical divisions, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_vdivs; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(10) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 10) { + // Get reference power level, step 1 + ds << TQString("GETREFERENCEPOWERLEVEL"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(11) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 11) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get reference power level, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_rpower; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(12) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 12) { + // Get vertical division scale, step 1 + ds << TQString("GETVERTDIVSCALE"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(13) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 13) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get vertical division scale, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_vscale; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(14) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 14) { + // Get center frequency, step 1 + ds << TQString("GETCENTERFREQUENCY"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(15) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 15) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get center frequency, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_centerfreq; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + SET_NEXT_STATE(16) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 16) { + // Get frequency span, step 1 + ds << TQString("GETFREQUENCYSPAN"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(17) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 17) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get frequency span, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_spanfreq; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { + // Update display widget(s) + updateGraticule(); + } + + if (result == "ACK") { + SET_NEXT_STATE(18) + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 18) { + // Get trace, step 1 + ds << TQString("GETSPECTRUMTRACE"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(19) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 19) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get trace, step 2 + TQDoubleArray trace; + TQString result; + ds >> result; + if (result == "ACK") { + ds >> trace; + } + m_socket->clearFrameTail(); + + if (result == "ACK") { +#if 1 + // Trace grap is slow on most instruments + // Put in the next trace request before processing the trace we just got so as to increase the overall update rate + if (m_commHandlerMode == 0) { + // Get trace, step 1 + ds << TQString("GETSPECTRUMTRACE"); + m_socket->writeEndOfFrame(); + } + +#endif + // Update display widget(s) + m_traceWidget->setSamples(0, trace); + m_base->traceZoomWidget->setSamples(0, trace); + postProcessTrace(); + m_traceWidget->repaint(true); + m_base->traceZoomWidget->repaint(true); + } + + + if (result == "ACK") { +#if 0 + //SET_NEXT_STATE(2) + SET_NEXT_STATE(18) + EXEC_NEXT_STATE_IMMEDIATELY +#else + SET_NEXT_STATE(19) + EXEC_NEXT_STATE_IMMEDIATELY +#endif + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerState == 255) { + // Execute pending command + m_commHandlerMode = 2; + m_socket->clearIncomingData(); + EXEC_NEXT_STATE_IMMEDIATELY + } + SET_WATCHDOG_TIMER + } + else if (m_commHandlerMode == 2) { + if (m_commHandlerCommandState == 0) { + m_commHandlerMode = 0; + m_commHandlerState = 10; + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerCommandState == 1) { + // Set reference power level + ds << TQString("SETREFERENCEPOWERLEVEL"); + ds << m_rpower; + m_socket->writeEndOfFrame(); + + m_commHandlerCommandState = 2; + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerCommandState == 2) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Set reference power level, step 2 + TQString result; + ds >> result; + m_socket->clearFrameTail(); + + if (result == "ACK") { + m_commHandlerCommandState = 3; + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + else if (m_commHandlerCommandState == 3) { + // Get reference power level, step 1 + ds << TQString("GETREFERENCEPOWERLEVEL"); + m_socket->writeEndOfFrame(); + + m_commHandlerCommandState = 4; + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerCommandState == 4) { + // Get response data + if (m_socket->canReadFrame()) { + PAT_WATCHDOG_TIMER + + // Get reference power level, step 2 + TQString result; + ds >> result; + if (result == "ACK") { + ds >> m_rpower; + } + m_socket->clearFrameTail(); + + // Update display as needed + updateGraticule(); + + if (result == "ACK") { + m_commHandlerCommandState = 0; + EXEC_NEXT_STATE_IMMEDIATELY + } + else { + COMMUNICATIONS_FAILED + } + } + else { + if (!m_updateTimeoutTimer->isActive()) { + UPDATEDISPLAY_TIMEOUT + } + } + } + } + } + else { + m_commHandlerState = 0; + m_commHandlerCommandState = 0; + } + + processLockouts(); + + m_instrumentMutex->unlock(); +} + +void ScopePart::postProcessTrace() { + return; +} + +void ScopePart::updateZoomWidgetLimits(const TQRectF& zoomRect) { + TQRectF fullZoomRect = m_traceWidget->displayLimits(0); + double widthSpan = fullZoomRect.width()-fullZoomRect.x(); + double heightSpan = fullZoomRect.height()-fullZoomRect.y(); + + TQRectF zoomLimitsRect((fullZoomRect.x()+(widthSpan*(zoomRect.x()/100.0))), (fullZoomRect.y()+(heightSpan*(zoomRect.y()/100.0))), (fullZoomRect.x()+(widthSpan*((zoomRect.x()/100.0)+(zoomRect.width()/100.0)))), (fullZoomRect.y()+(heightSpan*((zoomRect.y()/100.0)+(zoomRect.height()/100.0))))); + + m_base->traceZoomWidget->setDisplayLimits(0, zoomLimitsRect); +} + +void ScopePart::updateGraticule() { + m_traceWidget->setNumberOfSamples(0, m_samplesInTrace); + m_traceWidget->setNumberOfHorizontalDivisions(m_hdivs); + m_traceWidget->setNumberOfVerticalDivisions(m_vdivs); + m_base->traceZoomWidget->setNumberOfSamples(0, m_samplesInTrace); + m_base->traceZoomWidget->setNumberOfHorizontalDivisions(m_hdivs); + m_base->traceZoomWidget->setNumberOfVerticalDivisions(m_vdivs); + + m_leftFrequency = m_centerfreq - (m_spanfreq/2.0); + m_rightFrequency = m_centerfreq + (m_spanfreq/2.0); + + double freqincr = (m_rightFrequency-m_leftFrequency)/m_samplesInTrace; + double freqpos = m_leftFrequency; + TQDoubleArray tracepositions; + tracepositions.resize(m_samplesInTrace); + for (int i=0; i<m_samplesInTrace; i++) { + tracepositions[i] = freqpos; + freqpos = freqpos + freqincr; + } + m_traceWidget->setPositions(0, tracepositions); + m_traceWidget->setDisplayLimits(0, TQRectF(m_leftFrequency, m_rpower, m_rightFrequency, m_rpower-(m_vscale*m_vdivs))); + m_base->traceZoomWidget->setPositions(0, tracepositions); + updateZoomWidgetLimits(m_traceWidget->zoomBox()); + + // Also update controls + m_base->saRefLevel->blockSignals(true); + m_base->saRefLevel->setFloatValue(m_rpower); + m_base->saRefLevel->blockSignals(false); +} + +void ScopePart::saRefLevelChanged(double newval) { + if (m_commHandlerMode < 2) { + m_rpower = newval; + m_commHandlerMode = 1; + m_commHandlerCommandState = 1; + mainEventLoop(); + } +} + +KAboutData* ScopePart::createAboutData() { + return new KAboutData( APP_NAME, I18N_NOOP( APP_PRETTYNAME ), APP_VERSION ); +} + +} //namespace RemoteLab + +#include "part.moc" diff --git a/clients/tde/src/part/scope/part.h b/clients/tde/src/part/scope/part.h new file mode 100644 index 0000000..2a988da --- /dev/null +++ b/clients/tde/src/part/scope/part.h @@ -0,0 +1,77 @@ +//Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (C) 2012 +//Copyright: See COPYING file that comes with this distribution + +#ifndef REMOTELAB_SCOPEPART_H +#define REMOTELAB_SCOPEPART_H + +#include <kparts/browserextension.h> +#include <kparts/statusbarextension.h> +#include <kparts/part.h> +#include <kurl.h> + +#include <tqtrla.h> + +class KAboutData; +using KParts::StatusBarExtension; +class TraceWidget; +class TQSocket; +class TQTimer; +class TQMutex; +class TQRectF; +class ScopeBase; + +namespace RemoteLab +{ + class ScopePart : public KParts::RemoteInstrumentPart + { + Q_OBJECT + + public: + ScopePart( QWidget *, const char *, TQObject *, const char *, const TQStringList&); + ~ScopePart(); + + virtual bool openFile() { return false; } // pure virtual in the base class + virtual bool closeURL(); + static KAboutData *createAboutData(); + + public slots: + virtual bool openURL(const KURL &url); + void updateZoomWidgetLimits(const TQRectF& zoomRect); + + private slots: + void postInit(); + void processLockouts(); + void updateGraticule(); + void connectionFinishedCallback(); + void disconnectFromServerCallback(); + void connectionStatusChangedCallback(); + void setTickerMessage(TQString message); + void mainEventLoop(); + virtual void postProcessTrace(); + void saRefLevelChanged(double); + + private: + TraceWidget* m_traceWidget; + int m_commHandlerState; + int m_commHandlerMode; + int m_commHandlerCommandState; + TQTimer* m_forcedUpdateTimer; + TQTimer* m_updateTimeoutTimer; + bool m_connectionActiveAndValid; + unsigned char m_tickerState; + TQ_INT16 m_samplesInTrace; + double m_leftFrequency; + double m_rightFrequency; + TQ_INT16 m_hdivs; + TQ_INT16 m_vdivs; + double m_centerfreq; + double m_spanfreq; + double m_rpower; + double m_vscale; + ScopeBase* m_base; + TQMutex* m_instrumentMutex; + bool stopTraceUpdate; + }; +} + +#endif |