diff --git a/.hgignore b/.hgignore new file mode 100644 --- /dev/null +++ b/.hgignore @@ -0,0 +1,9 @@ +syntax: glob +*.o +*.so +*.so.1 +*.so.1.0 +*.so.1.0.0 +*~ +*moc_* + diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,142 @@ +############################################################################# +# Makefile for building: PAULs_LPPMON_PLUGINS +# Generated by qmake (2.01a) (Qt 4.8.3) on: Thu Nov 29 09:03:10 2012 +# Project: PAULs_LPPMON_PLUGINS.pro +# Template: subdirs +# Command: /usr/bin/qmake-qt4 -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile PAULs_LPPMON_PLUGINS.pro +############################################################################# + +first: make_default +MAKEFILE = Makefile +QMAKE = /usr/bin/qmake-qt4 +DEL_FILE = rm -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +COPY = cp -f +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_PROGRAM = install -m 755 -p +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +SUBTARGETS = \ + sub-rmapplugin + +rmapplugin/$(MAKEFILE): + @$(CHK_DIR_EXISTS) rmapplugin/ || $(MKDIR) rmapplugin/ + cd rmapplugin/ && $(QMAKE) /opt/LPPMON_PLUGINS_PAUL/rmapplugin/rmapplugin.pro -spec /usr/lib64/qt4/mkspecs/linux-g++ -o $(MAKEFILE) +sub-rmapplugin-qmake_all: FORCE + @$(CHK_DIR_EXISTS) rmapplugin/ || $(MKDIR) rmapplugin/ + cd rmapplugin/ && $(QMAKE) /opt/LPPMON_PLUGINS_PAUL/rmapplugin/rmapplugin.pro -spec /usr/lib64/qt4/mkspecs/linux-g++ -o $(MAKEFILE) +sub-rmapplugin: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) +sub-rmapplugin-make_default-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) +sub-rmapplugin-make_default: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) +sub-rmapplugin-make_first-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) first +sub-rmapplugin-make_first: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) first +sub-rmapplugin-all-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) all +sub-rmapplugin-all: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) all +sub-rmapplugin-clean-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) clean +sub-rmapplugin-clean: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) clean +sub-rmapplugin-distclean-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) distclean +sub-rmapplugin-distclean: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) distclean +sub-rmapplugin-install_subtargets-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) install +sub-rmapplugin-install_subtargets: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) install +sub-rmapplugin-uninstall_subtargets-ordered: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) uninstall +sub-rmapplugin-uninstall_subtargets: rmapplugin/$(MAKEFILE) FORCE + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) uninstall + +Makefile: PAULs_LPPMON_PLUGINS.pro /usr/lib64/qt4/mkspecs/linux-g++/qmake.conf /usr/lib64/qt4/mkspecs/common/unix.conf \ + /usr/lib64/qt4/mkspecs/common/linux.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base-unix.conf \ + /usr/lib64/qt4/mkspecs/common/g++-base.conf \ + /usr/lib64/qt4/mkspecs/common/g++-unix.conf \ + /usr/lib64/qt4/mkspecs/qconfig.pri \ + /usr/lib64/qt4/mkspecs/modules/qt_webkit_version.pri \ + /usr/lib64/qt4/mkspecs/features/qt_functions.prf \ + /usr/lib64/qt4/mkspecs/features/qt_config.prf \ + /usr/lib64/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/lib64/qt4/mkspecs/features/default_pre.prf \ + /usr/lib64/qt4/mkspecs/features/release.prf \ + /usr/lib64/qt4/mkspecs/features/default_post.prf \ + /usr/lib64/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \ + /usr/lib64/qt4/mkspecs/features/warn_on.prf \ + /usr/lib64/qt4/mkspecs/features/qt.prf \ + /usr/lib64/qt4/mkspecs/features/unix/thread.prf \ + /usr/lib64/qt4/mkspecs/features/moc.prf \ + /usr/lib64/qt4/mkspecs/features/resources.prf \ + /usr/lib64/qt4/mkspecs/features/uic.prf \ + /usr/lib64/qt4/mkspecs/features/yacc.prf \ + /usr/lib64/qt4/mkspecs/features/lex.prf \ + /usr/lib64/qt4/mkspecs/features/include_source_dir.prf + $(QMAKE) -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile PAULs_LPPMON_PLUGINS.pro +/usr/lib64/qt4/mkspecs/common/unix.conf: +/usr/lib64/qt4/mkspecs/common/linux.conf: +/usr/lib64/qt4/mkspecs/common/gcc-base.conf: +/usr/lib64/qt4/mkspecs/common/gcc-base-unix.conf: +/usr/lib64/qt4/mkspecs/common/g++-base.conf: +/usr/lib64/qt4/mkspecs/common/g++-unix.conf: +/usr/lib64/qt4/mkspecs/qconfig.pri: +/usr/lib64/qt4/mkspecs/modules/qt_webkit_version.pri: +/usr/lib64/qt4/mkspecs/features/qt_functions.prf: +/usr/lib64/qt4/mkspecs/features/qt_config.prf: +/usr/lib64/qt4/mkspecs/features/exclusive_builds.prf: +/usr/lib64/qt4/mkspecs/features/default_pre.prf: +/usr/lib64/qt4/mkspecs/features/release.prf: +/usr/lib64/qt4/mkspecs/features/default_post.prf: +/usr/lib64/qt4/mkspecs/features/unix/gdb_dwarf_index.prf: +/usr/lib64/qt4/mkspecs/features/warn_on.prf: +/usr/lib64/qt4/mkspecs/features/qt.prf: +/usr/lib64/qt4/mkspecs/features/unix/thread.prf: +/usr/lib64/qt4/mkspecs/features/moc.prf: +/usr/lib64/qt4/mkspecs/features/resources.prf: +/usr/lib64/qt4/mkspecs/features/uic.prf: +/usr/lib64/qt4/mkspecs/features/yacc.prf: +/usr/lib64/qt4/mkspecs/features/lex.prf: +/usr/lib64/qt4/mkspecs/features/include_source_dir.prf: +qmake: qmake_all FORCE + @$(QMAKE) -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile PAULs_LPPMON_PLUGINS.pro + +qmake_all: sub-rmapplugin-qmake_all FORCE + +make_default: sub-rmapplugin-make_default-ordered FORCE +make_first: sub-rmapplugin-make_first-ordered FORCE +all: sub-rmapplugin-all-ordered FORCE +clean: sub-rmapplugin-clean-ordered FORCE +distclean: sub-rmapplugin-distclean-ordered FORCE + -$(DEL_FILE) Makefile +install_subtargets: sub-rmapplugin-install_subtargets-ordered FORCE +uninstall_subtargets: sub-rmapplugin-uninstall_subtargets-ordered FORCE + +sub-rmapplugin-check_ordered: rmapplugin/$(MAKEFILE) + cd rmapplugin/ && $(MAKE) -f $(MAKEFILE) check +check: sub-rmapplugin-check_ordered + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all +install: install_subtargets FORCE + +uninstall: uninstall_subtargets FORCE + +FORCE: + diff --git a/PAULs_LPPMON_PLUGINS.pro b/PAULs_LPPMON_PLUGINS.pro new file mode 100755 --- /dev/null +++ b/PAULs_LPPMON_PLUGINS.pro @@ -0,0 +1,11 @@ +TEMPLATE = subdirs +CONFIG += ordered + +win32:LPPMONCFG = /opt/lppmon +unix:LPPMONCFG = /etc/lppmon + +SUBDIRS = \ + rmapplugin + + +#include( $${LPPMONCFG}/lppmonplugin.prf) diff --git a/PAULs_LPPMON_PLUGINS.pro.user b/PAULs_LPPMON_PLUGINS.pro.user new file mode 100644 --- /dev/null +++ b/PAULs_LPPMON_PLUGINS.pro.user @@ -0,0 +1,264 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + System + false + 4 + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + 0 + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Qt 4.8.2 in PATH (System) Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /opt/LPPMON_PLUGINS_PAUL + 1 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Qt 4.8.2 in PATH (System) Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /opt/LPPMON_PLUGINS_PAUL + 1 + false + + 2 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + No deployment + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 2 + lppmon + false + + %{buildDir} + Run lppmon + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {2e58a81f-9962-4bba-ae6b-760177f0656c} + + + ProjectExplorer.Project.Updater.FileVersion + 10 + + diff --git a/common_PLE/gresbstatusenquiry.cpp b/common_PLE/gresbstatusenquiry.cpp new file mode 100755 --- /dev/null +++ b/common_PLE/gresbstatusenquiry.cpp @@ -0,0 +1,31 @@ +#include "gresbstatusenquiry.h" +#include + +gresbStatusEnquiry::gresbStatusEnquiry(QWidget *parent) : + QWidget(parent) +{ + mainLayout = new QGridLayout; + readSPWStatusButton = new QPushButton(tr("Read SpaceWire Status")); + statusQueryTable = new QTableWidget(10, 3); + statusQueryTable->setHorizontalHeaderLabels(QStringList() << "link 0" << "link 1" << "link 2"); + statusQueryTable->setVerticalHeaderLabels(QStringList() << "Running" + << "Clock divisor" + << "Received" + << "Packets" + << "Data (bytes)" + << "EEPs" + << "Truncated" + << "Transmitted" + << "Packets" + << "Data (bytes)"); + for (int r = 0; r < 10; r++) + { + for (int c = 0; c < 3; c++) + { + statusQueryTable->setItem(r, c, new QTableWidgetItem("-")); + } + } + mainLayout->addWidget(statusQueryTable,0 , 0, 0); + mainLayout->addWidget(readSPWStatusButton,1, 0, 0); + setLayout(mainLayout); +} diff --git a/common_PLE/gresbstatusenquiry.h b/common_PLE/gresbstatusenquiry.h new file mode 100755 --- /dev/null +++ b/common_PLE/gresbstatusenquiry.h @@ -0,0 +1,63 @@ +#ifndef GRESBSTATUSENQUIRY_H +#define GRESBSTATUSENQUIRY_H + +#include +#include +#include +#include +#include + +enum GresbStatusQueryOption{ + LinkStatus, + LinkStatistics, + NodeAddressStatistics, + GetRoute}; + +struct gresb_status_query_str +{ + char protocolIdentifier; + char reserved1; + char reserved0; + char option; + char value3; + char value2; + char value1; + char value0; +}; +typedef gresb_status_query_str gresb_status_query_t; + +struct gresb_link_status_reply_str +{ + char byte3; + char byte2; + char byte1; + char byte0; +}; +typedef gresb_link_status_reply_str gresb_link_status_reply_t; + +struct gresb_link_statistics_reply_str +{ + char numberOfPacketsReceived[4]; + char sizeOfDataReceived[4]; + char numberOfPacketsWithEEPReceived[4]; + char numberOfTruncatedPacketsReceived[4]; + char numberOfPacketsTransmitted[4]; + char sizeOfDataTransmitted[4]; +}; +typedef gresb_link_statistics_reply_str gresb_link_statistics_reply_t; + +class gresbStatusEnquiry : public QWidget +{ + Q_OBJECT +public: + explicit gresbStatusEnquiry(QWidget *parent = 0); + QGridLayout* mainLayout; + QTableWidget* statusQueryTable; + QPushButton* readSPWStatusButton; + +signals: + +public slots: +}; + +#endif // GRESBSTATUSENQUIRY_H diff --git a/common_PLE/gresbstatusqueryTYPES.h b/common_PLE/gresbstatusqueryTYPES.h new file mode 100755 --- /dev/null +++ b/common_PLE/gresbstatusqueryTYPES.h @@ -0,0 +1,7 @@ +#ifndef GRESBSTATUSQUERY_H +#define GRESBSTATUSQUERY_H + + + + +#endif // GRESBSTATUSQUERY_H diff --git a/common_PLE/qipdialogbox.cpp b/common_PLE/qipdialogbox.cpp new file mode 100755 --- /dev/null +++ b/common_PLE/qipdialogbox.cpp @@ -0,0 +1,69 @@ +#include "qipdialogbox.h" +#include +#include +#include +#include +#include +#include + +QIPDialogBox::QIPDialogBox(QWidget *parent) : + QWidget(parent) +{ + //labelGRESBIP = new QLabel(tr("IP not set")); + QHBoxLayout *addressLayout = new QHBoxLayout; + QVBoxLayout *mainLayout = new QVBoxLayout; + addressPart1 = new QSpinBox; + addressPart2 = new QSpinBox; + addressPart3 = new QSpinBox; + addressPart4 = new QSpinBox; + + addressPart1->setRange(0, 255); + addressPart1->setValue(129); + addressPart1->setButtonSymbols(QAbstractSpinBox::NoButtons); + + addressPart2->setRange(0, 255); + addressPart2->setValue(104); + addressPart2->setButtonSymbols(QAbstractSpinBox::NoButtons); + + addressPart3->setRange(0, 255); + addressPart3->setValue(27); + addressPart3->setButtonSymbols(QAbstractSpinBox::NoButtons); + + addressPart4->setRange(0, 255); + addressPart4->setValue(113); + addressPart4->setButtonSymbols(QAbstractSpinBox::NoButtons); + + valueChanged(); + + connect(addressPart1, SIGNAL(valueChanged(int)), this, SLOT(valueChanged())); + connect(addressPart2, SIGNAL(valueChanged(int)), this, SLOT(valueChanged())); + connect(addressPart3, SIGNAL(valueChanged(int)), this, SLOT(valueChanged())); + connect(addressPart4, SIGNAL(valueChanged(int)), this, SLOT(valueChanged())); + + addressLayout->addWidget(addressPart1); + addressLayout->addWidget(addressPart2); + addressLayout->addWidget(addressPart3); + addressLayout->addWidget(addressPart4); + mainLayout->addLayout(addressLayout); + //mainLayout->addWidget(labelGRESBIP); + + setLayout(mainLayout); +} + +void QIPDialogBox::valueChanged() // SLOT +{ + gresbIP = addressPart1->cleanText(); + gresbIP.append("."); + gresbIP.append(addressPart2->cleanText()); + gresbIP.append("."); + gresbIP.append(addressPart3->cleanText()); + gresbIP.append("."); + gresbIP.append(addressPart4->cleanText()); + //labelGRESBIP->setText("IP used for the gresb module: " + gresbIP); +} + +QString QIPDialogBox::getGRESBIP() +{ + return(gresbIP); +} + diff --git a/common_PLE/qipdialogbox.h b/common_PLE/qipdialogbox.h new file mode 100755 --- /dev/null +++ b/common_PLE/qipdialogbox.h @@ -0,0 +1,30 @@ +#ifndef WIDGETADDRESS_H +#define WIDGETADDRESS_H + +#include +#include +#include +#include + +class QIPDialogBox : public QWidget +{ + Q_OBJECT +public: + explicit QIPDialogBox(QWidget *parent = 0); + QString getGRESBIP(); + +signals: + +public slots: + void valueChanged(); + +private: + QSpinBox *addressPart1; + QSpinBox *addressPart2; + QSpinBox *addressPart3; + QSpinBox *addressPart4; + //QLabel * labelGRESBIP; + QString gresbIP; +}; + +#endif // WIDGETADDRESS_H diff --git a/rmapplugin/Makefile b/rmapplugin/Makefile new file mode 100644 --- /dev/null +++ b/rmapplugin/Makefile @@ -0,0 +1,410 @@ +############################################################################# +# Makefile for building: librmapplugin.so.1.0.0 +# Generated by qmake (2.01a) (Qt 4.8.3) on: Thu Nov 29 09:38:20 2012 +# Project: rmapplugin.pro +# Template: lib +# Command: /usr/bin/qmake-qt4 -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile rmapplugin.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DPLUGIN=rmapplugin -DPLUGINHEADER="\"rmapplugin.h\"" -Ddriver_Name="\"RMAPPlugin\"" -Ddriver_Author="\"Paul Leroy paul.leroy@lpp.polytechnique.fr\"" -Ddriver_Version="\"1.1.2\"" -Ddriver_Description="\"AHB bus controler, works with Gaisler's AHB plugn' play bus.\"" -Ddriver_can_be_root=1 -Ddriver_can_be_child=0 -Ddriver_VID=0 -Ddriver_PID=0 -DUNIXTRANSLATIONPATH -DLPPMON_PLUGINS_INSTALL_PATH="QDir::homePath()+\"/.lppmon/plugins\"" -DLPPMON_TRANSLATION_PATH="\"/etc/lppmon/translations\"" -DLPPMONPLUGIN_LIBRARY -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +CXXFLAGS = -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -O2 -I/usr/include/python2.7 -I/usr/include/python2.7 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +INCPATH = -I/usr/lib64/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtNetwork -I/usr/include/QtGui -I/usr/include -I. -I../common_PLE -I../spw_usb_driver_v2.61/inc -I/usr/include/lppmon/pluginsInterface -I/usr/include/PythonQt -Imoc +LINK = g++ +LFLAGS = -Wl,-O1 -Wl,-z,relro -shared -Wl,-soname,librmapplugin.so.1 +LIBS = $(SUBLIBS) -L/usr/lib64 ../spw_usb_driver_v2.61/lib/libSpaceWireUSBAPI.so -ldl -lutil -lm -lpython2.7 -lPythonQt_QtAll -lPythonQt -lQtGui -lQtNetwork -lQtCore -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake-qt4 +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = obj/ + +####### Files + +SOURCES = rmapplugin.cpp \ + rmappluginui.cpp \ + rmapoperations.cpp \ + ccsds.cpp \ + spwpacketreceiver.cpp \ + ../common_PLE/qipdialogbox.cpp \ + ../common_PLE/gresbstatusenquiry.cpp \ + spectralmatricesdmasimulator.cpp \ + rmappluginpythonwrapper.cpp \ + stardundee.cpp \ + /usr/include/lppmon/pluginsInterface/lppmonplugininterface.cpp moc/moc_rmappluginui.cpp \ + moc/moc_rmapplugin.cpp \ + moc/moc_spwpacketreceiver.cpp \ + moc/moc_qipdialogbox.cpp \ + moc/moc_gresbstatusenquiry.cpp \ + moc/moc_spectralmatricesdmasimulator.cpp \ + moc/moc_rmappluginpythonwrapper.cpp \ + moc/moc_stardundee.cpp \ + moc/moc_genericPySysdriver.cpp \ + moc/moc_lppmonplugin.cpp +OBJECTS = obj/rmapplugin.o \ + obj/rmappluginui.o \ + obj/rmapoperations.o \ + obj/ccsds.o \ + obj/spwpacketreceiver.o \ + obj/qipdialogbox.o \ + obj/gresbstatusenquiry.o \ + obj/spectralmatricesdmasimulator.o \ + obj/rmappluginpythonwrapper.o \ + obj/stardundee.o \ + obj/lppmonplugininterface.o \ + obj/moc_rmappluginui.o \ + obj/moc_rmapplugin.o \ + obj/moc_spwpacketreceiver.o \ + obj/moc_qipdialogbox.o \ + obj/moc_gresbstatusenquiry.o \ + obj/moc_spectralmatricesdmasimulator.o \ + obj/moc_rmappluginpythonwrapper.o \ + obj/moc_stardundee.o \ + obj/moc_genericPySysdriver.o \ + obj/moc_lppmonplugin.o +DIST = /usr/lib64/qt4/mkspecs/common/unix.conf \ + /usr/lib64/qt4/mkspecs/common/linux.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base-unix.conf \ + /usr/lib64/qt4/mkspecs/common/g++-base.conf \ + /usr/lib64/qt4/mkspecs/common/g++-unix.conf \ + /usr/lib64/qt4/mkspecs/qconfig.pri \ + /usr/lib64/qt4/mkspecs/modules/qt_webkit_version.pri \ + /usr/lib64/qt4/mkspecs/features/qt_functions.prf \ + /usr/lib64/qt4/mkspecs/features/qt_config.prf \ + /usr/lib64/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/lib64/qt4/mkspecs/features/default_pre.prf \ + /usr/lib64/qt4/mkspecs/features/release.prf \ + /usr/lib64/qt4/mkspecs/features/default_post.prf \ + /usr/lib64/qt4/mkspecs/features/lppmonplugin.prf \ + /usr/lib64/qt4/mkspecs/features/pythonqt.prf \ + /usr/lib64/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \ + /usr/lib64/qt4/mkspecs/features/warn_on.prf \ + /usr/lib64/qt4/mkspecs/features/qt.prf \ + /usr/lib64/qt4/mkspecs/features/unix/thread.prf \ + /usr/lib64/qt4/mkspecs/features/moc.prf \ + /usr/lib64/qt4/mkspecs/features/resources.prf \ + /usr/lib64/qt4/mkspecs/features/uic.prf \ + /usr/lib64/qt4/mkspecs/features/yacc.prf \ + /usr/lib64/qt4/mkspecs/features/lex.prf \ + /usr/lib64/qt4/mkspecs/features/include_source_dir.prf \ + rmapplugin.pro +QMAKE_TARGET = rmapplugin +DESTDIR = bin/ +TARGET = librmapplugin.so.1.0.0 +TARGETA = bin/librmapplugin.a +TARGETD = librmapplugin.so.1.0.0 +TARGET0 = librmapplugin.so +TARGET1 = librmapplugin.so.1 +TARGET2 = librmapplugin.so.1.0 + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile bin/$(TARGET) + +bin/$(TARGET): $(OBJECTS) $(SUBLIBS) $(OBJCOMP) + @$(CHK_DIR_EXISTS) bin/ || $(MKDIR) bin/ + -$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP) + -ln -s $(TARGET) $(TARGET0) + -ln -s $(TARGET) $(TARGET1) + -ln -s $(TARGET) $(TARGET2) + -$(DEL_FILE) bin/$(TARGET) + -$(DEL_FILE) bin/$(TARGET0) + -$(DEL_FILE) bin/$(TARGET1) + -$(DEL_FILE) bin/$(TARGET2) + -$(MOVE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) bin/ + + + +staticlib: $(TARGETA) + +$(TARGETA): $(OBJECTS) $(OBJCOMP) + -$(DEL_FILE) $(TARGETA) + $(AR) $(TARGETA) $(OBJECTS) + +Makefile: rmapplugin.pro /usr/lib64/qt4/mkspecs/linux-g++/qmake.conf /usr/lib64/qt4/mkspecs/common/unix.conf \ + /usr/lib64/qt4/mkspecs/common/linux.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base.conf \ + /usr/lib64/qt4/mkspecs/common/gcc-base-unix.conf \ + /usr/lib64/qt4/mkspecs/common/g++-base.conf \ + /usr/lib64/qt4/mkspecs/common/g++-unix.conf \ + /usr/lib64/qt4/mkspecs/qconfig.pri \ + /usr/lib64/qt4/mkspecs/modules/qt_webkit_version.pri \ + /usr/lib64/qt4/mkspecs/features/qt_functions.prf \ + /usr/lib64/qt4/mkspecs/features/qt_config.prf \ + /usr/lib64/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/lib64/qt4/mkspecs/features/default_pre.prf \ + /usr/lib64/qt4/mkspecs/features/release.prf \ + /usr/lib64/qt4/mkspecs/features/default_post.prf \ + /usr/lib64/qt4/mkspecs/features/lppmonplugin.prf \ + /usr/lib64/qt4/mkspecs/features/pythonqt.prf \ + /usr/lib64/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \ + /usr/lib64/qt4/mkspecs/features/warn_on.prf \ + /usr/lib64/qt4/mkspecs/features/qt.prf \ + /usr/lib64/qt4/mkspecs/features/unix/thread.prf \ + /usr/lib64/qt4/mkspecs/features/moc.prf \ + /usr/lib64/qt4/mkspecs/features/resources.prf \ + /usr/lib64/qt4/mkspecs/features/uic.prf \ + /usr/lib64/qt4/mkspecs/features/yacc.prf \ + /usr/lib64/qt4/mkspecs/features/lex.prf \ + /usr/lib64/qt4/mkspecs/features/include_source_dir.prf \ + /usr/lib64/libQtGui.prl \ + /usr/lib64/libQtCore.prl \ + /usr/lib64/libQtNetwork.prl + $(QMAKE) -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile rmapplugin.pro +/usr/lib64/qt4/mkspecs/common/unix.conf: +/usr/lib64/qt4/mkspecs/common/linux.conf: +/usr/lib64/qt4/mkspecs/common/gcc-base.conf: +/usr/lib64/qt4/mkspecs/common/gcc-base-unix.conf: +/usr/lib64/qt4/mkspecs/common/g++-base.conf: +/usr/lib64/qt4/mkspecs/common/g++-unix.conf: +/usr/lib64/qt4/mkspecs/qconfig.pri: +/usr/lib64/qt4/mkspecs/modules/qt_webkit_version.pri: +/usr/lib64/qt4/mkspecs/features/qt_functions.prf: +/usr/lib64/qt4/mkspecs/features/qt_config.prf: +/usr/lib64/qt4/mkspecs/features/exclusive_builds.prf: +/usr/lib64/qt4/mkspecs/features/default_pre.prf: +/usr/lib64/qt4/mkspecs/features/release.prf: +/usr/lib64/qt4/mkspecs/features/default_post.prf: +/usr/lib64/qt4/mkspecs/features/lppmonplugin.prf: +/usr/lib64/qt4/mkspecs/features/pythonqt.prf: +/usr/lib64/qt4/mkspecs/features/unix/gdb_dwarf_index.prf: +/usr/lib64/qt4/mkspecs/features/warn_on.prf: +/usr/lib64/qt4/mkspecs/features/qt.prf: +/usr/lib64/qt4/mkspecs/features/unix/thread.prf: +/usr/lib64/qt4/mkspecs/features/moc.prf: +/usr/lib64/qt4/mkspecs/features/resources.prf: +/usr/lib64/qt4/mkspecs/features/uic.prf: +/usr/lib64/qt4/mkspecs/features/yacc.prf: +/usr/lib64/qt4/mkspecs/features/lex.prf: +/usr/lib64/qt4/mkspecs/features/include_source_dir.prf: +/usr/lib64/libQtGui.prl: +/usr/lib64/libQtCore.prl: +/usr/lib64/libQtNetwork.prl: +qmake: FORCE + @$(QMAKE) -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile rmapplugin.pro + +dist: + @$(CHK_DIR_EXISTS) obj/rmapplugin1.0.0 || $(MKDIR) obj/rmapplugin1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) obj/rmapplugin1.0.0/ && $(COPY_FILE) --parents rmappluginui.h rmapplugin.h rmapoperations.h ccsds.h spwpacketreceiver.h ../common_PLE/qipdialogbox.h ../common_PLE/gresbstatusenquiry.h spectralmatricesdmasimulator.h rmappluginpythonwrapper.h stardundee.h ../spw_usb_driver_v2.61/inc/spw_usb_api.h /usr/include/genericPySysdriver.h /usr/include/lppmonplugin.h obj/rmapplugin1.0.0/ && $(COPY_FILE) --parents rmapplugin.cpp rmappluginui.cpp rmapoperations.cpp ccsds.cpp spwpacketreceiver.cpp ../common_PLE/qipdialogbox.cpp ../common_PLE/gresbstatusenquiry.cpp spectralmatricesdmasimulator.cpp rmappluginpythonwrapper.cpp stardundee.cpp /usr/include/lppmon/pluginsInterface/lppmonplugininterface.cpp obj/rmapplugin1.0.0/ && (cd `dirname obj/rmapplugin1.0.0` && $(TAR) rmapplugin1.0.0.tar rmapplugin1.0.0 && $(COMPRESS) rmapplugin1.0.0.tar) && $(MOVE) `dirname obj/rmapplugin1.0.0`/rmapplugin1.0.0.tar.gz . && $(DEL_FILE) -r obj/rmapplugin1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) bin/$(TARGET) + -$(DEL_FILE) bin/$(TARGET0) bin/$(TARGET1) bin/$(TARGET2) $(TARGETA) + -$(DEL_FILE) Makefile + + +check: first + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc/moc_rmappluginui.cpp moc/moc_rmapplugin.cpp moc/moc_spwpacketreceiver.cpp moc/moc_qipdialogbox.cpp moc/moc_gresbstatusenquiry.cpp moc/moc_spectralmatricesdmasimulator.cpp moc/moc_rmappluginpythonwrapper.cpp moc/moc_stardundee.cpp moc/moc_genericPySysdriver.cpp moc/moc_lppmonplugin.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc/moc_rmappluginui.cpp moc/moc_rmapplugin.cpp moc/moc_spwpacketreceiver.cpp moc/moc_qipdialogbox.cpp moc/moc_gresbstatusenquiry.cpp moc/moc_spectralmatricesdmasimulator.cpp moc/moc_rmappluginpythonwrapper.cpp moc/moc_stardundee.cpp moc/moc_genericPySysdriver.cpp moc/moc_lppmonplugin.cpp +moc/moc_rmappluginui.cpp: rmapoperations.h \ + spectralmatricesdmasimulator.h \ + rmappluginui.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) rmappluginui.h -o moc/moc_rmappluginui.cpp + +moc/moc_rmapplugin.cpp: rmappluginui.h \ + rmapoperations.h \ + spectralmatricesdmasimulator.h \ + ccsds.h \ + spwpacketreceiver.h \ + rmapplugin.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) rmapplugin.h -o moc/moc_rmapplugin.cpp + +moc/moc_spwpacketreceiver.cpp: spwpacketreceiver.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) spwpacketreceiver.h -o moc/moc_spwpacketreceiver.cpp + +moc/moc_qipdialogbox.cpp: ../common_PLE/qipdialogbox.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) ../common_PLE/qipdialogbox.h -o moc/moc_qipdialogbox.cpp + +moc/moc_gresbstatusenquiry.cpp: ../common_PLE/gresbstatusenquiry.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) ../common_PLE/gresbstatusenquiry.h -o moc/moc_gresbstatusenquiry.cpp + +moc/moc_spectralmatricesdmasimulator.cpp: spectralmatricesdmasimulator.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) spectralmatricesdmasimulator.h -o moc/moc_spectralmatricesdmasimulator.cpp + +moc/moc_rmappluginpythonwrapper.cpp: rmappluginpythonwrapper.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) rmappluginpythonwrapper.h -o moc/moc_rmappluginpythonwrapper.cpp + +moc/moc_stardundee.cpp: stardundee.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) stardundee.h -o moc/moc_stardundee.cpp + +moc/moc_genericPySysdriver.cpp: /usr/include/genericPySysdriver.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) /usr/include/genericPySysdriver.h -o moc/moc_genericPySysdriver.cpp + +moc/moc_lppmonplugin.cpp: /usr/include/lppmonplugin.h + /usr/lib64/qt4/bin/moc $(DEFINES) $(INCPATH) /usr/include/lppmonplugin.h -o moc/moc_lppmonplugin.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean + +####### Compile + +obj/rmapplugin.o: rmapplugin.cpp rmapplugin.h \ + rmappluginui.h \ + rmapoperations.h \ + spectralmatricesdmasimulator.h \ + ccsds.h \ + spwpacketreceiver.h \ + rmappluginpythonwrapper.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/rmapplugin.o rmapplugin.cpp + +obj/rmappluginui.o: rmappluginui.cpp rmapplugin.h \ + rmappluginui.h \ + rmapoperations.h \ + spectralmatricesdmasimulator.h \ + ccsds.h \ + spwpacketreceiver.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/rmappluginui.o rmappluginui.cpp + +obj/rmapoperations.o: rmapoperations.cpp rmapoperations.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/rmapoperations.o rmapoperations.cpp + +obj/ccsds.o: ccsds.cpp ccsds.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/ccsds.o ccsds.cpp + +obj/spwpacketreceiver.o: spwpacketreceiver.cpp spwpacketreceiver.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/spwpacketreceiver.o spwpacketreceiver.cpp + +obj/qipdialogbox.o: ../common_PLE/qipdialogbox.cpp ../common_PLE/qipdialogbox.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/qipdialogbox.o ../common_PLE/qipdialogbox.cpp + +obj/gresbstatusenquiry.o: ../common_PLE/gresbstatusenquiry.cpp ../common_PLE/gresbstatusenquiry.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/gresbstatusenquiry.o ../common_PLE/gresbstatusenquiry.cpp + +obj/spectralmatricesdmasimulator.o: spectralmatricesdmasimulator.cpp spectralmatricesdmasimulator.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/spectralmatricesdmasimulator.o spectralmatricesdmasimulator.cpp + +obj/rmappluginpythonwrapper.o: rmappluginpythonwrapper.cpp rmappluginpythonwrapper.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/rmappluginpythonwrapper.o rmappluginpythonwrapper.cpp + +obj/stardundee.o: stardundee.cpp stardundee.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/stardundee.o stardundee.cpp + +obj/lppmonplugininterface.o: /usr/include/lppmon/pluginsInterface/lppmonplugininterface.cpp /usr/include/lppmon/pluginsInterface/lppmonplugininterface.h \ + /usr/include/lppmon/pluginsInterface/lppmonplugininterface_global.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/lppmonplugininterface.o /usr/include/lppmon/pluginsInterface/lppmonplugininterface.cpp + +obj/moc_rmappluginui.o: moc/moc_rmappluginui.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_rmappluginui.o moc/moc_rmappluginui.cpp + +obj/moc_rmapplugin.o: moc/moc_rmapplugin.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_rmapplugin.o moc/moc_rmapplugin.cpp + +obj/moc_spwpacketreceiver.o: moc/moc_spwpacketreceiver.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_spwpacketreceiver.o moc/moc_spwpacketreceiver.cpp + +obj/moc_qipdialogbox.o: moc/moc_qipdialogbox.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_qipdialogbox.o moc/moc_qipdialogbox.cpp + +obj/moc_gresbstatusenquiry.o: moc/moc_gresbstatusenquiry.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_gresbstatusenquiry.o moc/moc_gresbstatusenquiry.cpp + +obj/moc_spectralmatricesdmasimulator.o: moc/moc_spectralmatricesdmasimulator.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_spectralmatricesdmasimulator.o moc/moc_spectralmatricesdmasimulator.cpp + +obj/moc_rmappluginpythonwrapper.o: moc/moc_rmappluginpythonwrapper.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_rmappluginpythonwrapper.o moc/moc_rmappluginpythonwrapper.cpp + +obj/moc_stardundee.o: moc/moc_stardundee.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_stardundee.o moc/moc_stardundee.cpp + +obj/moc_genericPySysdriver.o: moc/moc_genericPySysdriver.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_genericPySysdriver.o moc/moc_genericPySysdriver.cpp + +obj/moc_lppmonplugin.o: moc/moc_lppmonplugin.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_lppmonplugin.o moc/moc_lppmonplugin.cpp + +####### Install + +install_target: first FORCE + @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/home/paul/.lppmon/plugins/ || $(MKDIR) $(INSTALL_ROOT)/home/paul/.lppmon/plugins/ + -$(INSTALL_PROGRAM) "bin/$(TARGET)" "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET)" + -$(SYMLINK) "$(TARGET)" "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET0)" + -$(SYMLINK) "$(TARGET)" "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET1)" + -$(SYMLINK) "$(TARGET)" "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET2)" + +uninstall_target: FORCE + -$(DEL_FILE) "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET)" + -$(DEL_FILE) "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET0)" + -$(DEL_FILE) "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET1)" + -$(DEL_FILE) "$(INSTALL_ROOT)/home/paul/.lppmon/plugins/$(TARGET2)" + -$(DEL_DIR) $(INSTALL_ROOT)/home/paul/.lppmon/plugins/ + + +install: install_target FORCE + +uninstall: uninstall_target FORCE + +FORCE: + diff --git a/rmapplugin/ccsds.cpp b/rmapplugin/ccsds.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/ccsds.cpp @@ -0,0 +1,37 @@ +#include "ccsds.h" + +ccsds::ccsds(unsigned char data_field_header, + unsigned char processID, + unsigned int sequence_count, + unsigned int packet_length, + unsigned char acceptance, + unsigned int completion, + unsigned char service_type, + unsigned char service_subtype, + unsigned char sourceID) +{ + unsigned int packetID = 0; + ccsds_header = new ccsds_telecommand_source_packet_hdr_t ; + + packetID = packetID + (0b000<<13); // version number + packetID = packetID + (0b1<<12); // packet type + packetID = packetID + (data_field_header<<11); // data field header 1 if there is a datafield header + packetID = packetID + (processID<<4); // process ID 7 bits + packetID = packetID + (0b1100); // packet category '1100' + + ccsds_header->packetId1 = (unsigned char) (packetID>>8); + ccsds_header->packetId0 = (unsigned char) (packetID); + + ccsds_header->packetSequenceControl1 = (unsigned char) ((0b11<<6) + (sequence_count>>8)); + ccsds_header->packetSequenceControl0 = (unsigned char) (sequence_count); + + ccsds_header->packetLength1 = (unsigned char) (packet_length>>8); + ccsds_header->packetLength0 = (unsigned char) (packet_length); + + ccsds_header->dataFieldHeader3 = ccsds_header->dataFieldHeader3 + (0b0001<<4); + ccsds_header->dataFieldHeader3 = ccsds_header->dataFieldHeader3 + (completion<<3); + ccsds_header->dataFieldHeader3 = ccsds_header->dataFieldHeader3 + (acceptance); + ccsds_header->dataFieldHeader2 = service_type; + ccsds_header->dataFieldHeader1 = service_subtype; + ccsds_header->dataFieldHeader0 = sourceID; +} diff --git a/rmapplugin/ccsds.h b/rmapplugin/ccsds.h new file mode 100755 --- /dev/null +++ b/rmapplugin/ccsds.h @@ -0,0 +1,48 @@ +#ifndef CCSDS_H +#define CCSDS_H + +struct ccsds_telecommand_source_packet_hdr_str +{ + unsigned char packetId1; + unsigned char packetId0; + unsigned char packetSequenceControl1; + unsigned char packetSequenceControl0; + unsigned char packetLength1; + unsigned char packetLength0; + unsigned char dataFieldHeader3; + unsigned char dataFieldHeader2; + unsigned char dataFieldHeader1; + unsigned char dataFieldHeader0; +}; +typedef ccsds_telecommand_source_packet_hdr_str ccsds_telecommand_source_packet_hdr_t; + +struct ccsdsSourcePacket_pachetHeader_str +{ + unsigned char packetId1; + unsigned char packetId0; + unsigned char packetSequenceControl1; + unsigned char packetSequenceControl0; + unsigned char packetLength1; + unsigned char packetLength0; +}; +typedef ccsdsSourcePacket_pachetHeader_str ccsdsSourcePacket_pachetHeader_t; + +struct ccsdsTelemetrySourcePacket_dataFieldHeader_str +{ + unsigned char spare_PUS_spare; + unsigned char serviceType; + unsigned char serviceSubtype; + unsigned char destinationID; + unsigned char SCTime[6]; +}; +typedef ccsdsTelemetrySourcePacket_dataFieldHeader_str ccsdsTelemetrySourcePacket_dataFieldHeader_t; + +class ccsds +{ +public: + ccsds(unsigned char data_field_header, unsigned char processID, unsigned int sequence_count, unsigned int packet_length, unsigned char acceptance, unsigned int completion, + unsigned char service_type, unsigned char service_subtype, unsigned char sourceID); + ccsds_telecommand_source_packet_hdr_t *ccsds_header; +}; + +#endif // CCSDS_H diff --git a/rmapplugin/rmapoperations.cpp b/rmapplugin/rmapoperations.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/rmapoperations.cpp @@ -0,0 +1,95 @@ +#include "rmapoperations.h" + +RMAP::RMAP(RMAP_command_codes commandCode, char targetLogicalAddress, char initiatorLogicalAddress, int startAddress, int nbBytes, char* data) +{ + char packetType; // 2 most Significant Bits + char command; // 4 bits + char replyAddressLength; // 2 Least Significant Bits + int SPWPacketSize; + + // GRESB HEADER + if (data == NULL){ + SPWPacketSize = sizeof(RMAPHeader) ; + dataCRC = 0x00; + } + else{ + SPWPacketSize = sizeof(RMAPHeader) + nbBytes + 1 ; // SPW Packet = Header + Data + dataCRC + dataCRC = RMAPCalculateDataCRC(data, nbBytes); + } + GRESBHeader.GRESBProtocoleID = 0x00; // packets with protocole ID 0 have SpaceWire a packet as payload + GRESBHeader.SPWPacketSize2 = (SPWPacketSize>>16); + GRESBHeader.SPWPacketSize1 = (SPWPacketSize>>8); + GRESBHeader.SPWPacketSize0 = (SPWPacketSize); + + // SPACEWIRE HEADER + packetType = (char) 0b01; // 0b01 for a command, 0b00 for a reply + command = (char) commandCode; + replyAddressLength = (char) 0b00; // RMAP command: number of bytes in the reply address field + // RMAP reply: copy of the reply address field of the command + switch (commandCode){ + case writeSingle_noVer_noRep: + case writeSingle_noVer_Rep: + case writeSingle_ver_noRep: + case writeSingle_ver_rep: + if (nbBytes > 4) command = command + 1; // switch between Single and Incremental Read/Write operations + break; + default: + break; + } + RMAPHeader.targetLogicalAddress = targetLogicalAddress ; + RMAPHeader.protocolIdentifier = 0x01; // 0x01 is the protocole identifier for RMAP + RMAPHeader.instruction = (packetType<<6) + (command<<2) + (replyAddressLength); + RMAPHeader.key = 0; // used for command authorization + RMAPHeader.initiatorLogicalAddress = initiatorLogicalAddress; // 0 is the default address for the GRESB module + RMAPHeader.transactionIdentifier1 = 0x00; + RMAPHeader.transactionIdentifier0 = 0x01; + RMAPHeader.extendedAddress = 0x00; + RMAPHeader.address3 = (char) (startAddress>>24); + RMAPHeader.address2 = (char) (startAddress>>16); + RMAPHeader.address1 = (char) (startAddress>>8); + RMAPHeader.address0 = (char) (startAddress); + RMAPHeader.dataLength2 = (char) (nbBytes>>16); + RMAPHeader.dataLength1 = (char) (nbBytes>>8); + RMAPHeader.dataLength0 = (char) (nbBytes); + RMAPHeader.headerCRC = RMAPCalculateHeaderCRC(); +} + +unsigned char RMAP::RMAPCalculateCRC(unsigned char INCR, unsigned char INBYTE) +{ + return RMAP_CRCTable[INCR ^ INBYTE]; +} + +unsigned char RMAP::RMAPCalculateHeaderCRC() +{ + unsigned char INCR = 0; + + INCR = RMAPCalculateCRC(INCR, RMAPHeader.targetLogicalAddress); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.protocolIdentifier); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.instruction); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.key); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.initiatorLogicalAddress); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.transactionIdentifier1); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.transactionIdentifier0); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.extendedAddress); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.address3); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.address2); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.address1); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.address0); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.dataLength2); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.dataLength1); + INCR = RMAPCalculateCRC(INCR, RMAPHeader.dataLength0); + + return(INCR); +} + +unsigned char RMAP::RMAPCalculateDataCRC(char *data, int nbBytes) +{ + unsigned char INCR = 0; + + for (int k=0; k check Gaisler GRSPW for compliance + //char replyAddress[]; // not needed if logical addressing is used (replyAddressLength = 0b00) + char initiatorLogicalAddress; + char transactionIdentifier1; + char transactionIdentifier0; + char extendedAddress; + char address3; + char address2; + char address1; + char address0; + unsigned char dataLength2; + unsigned char dataLength1; + unsigned char dataLength0; + char headerCRC; +}; +typedef struct rmap_command_format_str rmap_command_format_t; + +struct rmap_write_reply_str +{ + unsigned char initiatorLogicalAddress; + unsigned char protocolIdentifier; + unsigned char instruction; + unsigned char status; + unsigned char targetLogicalAddress; + unsigned char transactionIdentifier1; + unsigned char transactionIdentifier2; + unsigned char headerCRC; +}; +typedef struct rmap_write_reply_str rmap_write_reply_t; + +struct rmap_read_reply_PcktHdr_str +{ + //char replyAddress[]; // not needed if logical addressing is used + char initiatorLogicalAddress; + char protocolIdentifier; + char instruction; + char status; + char targetLogicalAddress; + char transactionIdentifier1; + char transactionIdentifier0; + char reserved; + unsigned char dataLength2; + unsigned char dataLength1; + unsigned char dataLength0; + char headerCRC; +}; +typedef struct rmap_read_reply_PcktHdr_str rmap_read_reply_PcktHdr_t; + +struct rmap_gresb_header_str +{ + char GRESBProtocoleID; + unsigned char SPWPacketSize2; + unsigned char SPWPacketSize1; + unsigned char SPWPacketSize0; +}; +typedef struct rmap_gresb_header_str rmap_gresb_header_str; + +class RMAP +{ +public: + RMAP(RMAP_command_codes commandCode, + char targetLogicalAddress, + char initiatorLogicalAddress, + int startAddress, + int nbBytes, + char *data); + unsigned char RMAPCalculateCRC(unsigned char INCR, unsigned char INBYTE); // ECSS-E-ST-50-52C + unsigned char RMAPCalculateHeaderCRC(); + unsigned char RMAPCalculateDataCRC(char *data, int nbBytes); + rmap_gresb_header_str GRESBHeader; + rmap_command_format_t RMAPHeader; + char dataCRC; +}; + +#endif // RMAPOPERATIONS_H diff --git a/rmapplugin/rmapplugin.cpp b/rmapplugin/rmapplugin.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/rmapplugin.cpp @@ -0,0 +1,817 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the LPPMON Software +-- Copyright (C) 2012, Laboratory of Plasma Physics - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Paul LEROY +-- Mail : paul.leroy@lpp.polytechnique.fr +----------------------------------------------------------------------------*/ +#include "rmapplugin.h" +#include +#include +#include +#include + +rmapplugin::rmapplugin(QWidget *parent) + :lppmonplugin(parent,false) +{ + this->UI = new rmapPluginUI(); + this->setWindowTitle(tr("RMAP and SPW Communication")); + this->setWidget((QWidget*)this->UI); + RMAPSend_SOCKET = new QTcpSocket; + RMAPReceive_SOCKET = new QTcpSocket; + GRESBStatusQuery_SOCKET = new QTcpSocket; + spwPacketReceiverOBJECT = new spwpacketreceiver; + spwPacketReceiverOBJECT->gresbReceptionSocket = RMAPReceive_SOCKET; + timeCode = 0; + time_COARSE = 0; + time_FINE = 0; + + /*Python wrapper*/ + this->pyObject = new rmappluginPythonWrapper(); + connect(this->pyObject,SIGNAL(ReadSig(uint*,uint,uint)),this,SLOT(Read(uint*,uint,uint))); + connect(this->pyObject,SIGNAL(WriteSig(uint*,uint,uint)),this,SLOT(Write(uint*,uint,uint))); + /*==============*/ + + connect(UI->rmapOpenCommunicationButton, SIGNAL(clicked()), this, SLOT(RMAP_CONNECT())); + connect(UI->rmapCloseCommunicationButton, SIGNAL(clicked()), this, SLOT(RMAP_DISCONNECT())); + connect(RMAPSend_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(RMAPSendConnectionState(QAbstractSocket::SocketState))); + connect(RMAPReceive_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(RMAPReceiveConnectionState(QAbstractSocket::SocketState))); + connect(GRESBStatusQuery_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(GRESBConnectionState(QAbstractSocket::SocketState))); + connect(UI->gresbStatusQueryRetryButton, SIGNAL(clicked()), this, SLOT(reTestSPWLink())); + connect(this->UI->spwLinkStatusEnquiry->readSPWStatusButton, SIGNAL(clicked()), this, SLOT(GRESBStatusQuery())); + connect(this->RMAPReceive_SOCKET, SIGNAL(readyRead()), this->spwPacketReceiverOBJECT, SLOT(receiveSPWPacket())); + + // CCSDS + connect(this->UI->sendCCSDSCommandButton, SIGNAL(clicked()), this, SLOT(sendCCSDS())); + connect(this->UI->send_TC_LFR_UPDATE_TIME_Button, SIGNAL(clicked()), this, SLOT(send_TC_LFR_UPDATE_TIME())); + connect(this->UI->reset_TC_LFR_UPDATE_TIME_Button, SIGNAL(clicked()), this, SLOT(reset_TC_LFR_UPDATE_TIME())); + + // CONSOLE + connect(this->spwPacketReceiverOBJECT, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); + connect(this->UI->starDundee, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); + + // spectralMAtricesDMASimulator + connect(this->UI->spectralMatricesDMASimulator, SIGNAL(rmapplugginRead(uint*,uint,uint)), this, SLOT(Read(uint*,uint,uint))); + connect(this->UI->spectralMatricesDMASimulator, SIGNAL(rmapplugginWrite(uint*,uint,uint)), this, SLOT(Write(uint*,uint,uint))); + connect(this->UI->spectralMatricesDMASimulator, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); +} + +rmapplugin::~rmapplugin() +{ + if (!RMAPSend_SOCKET->isOpen()) RMAPSend_SOCKET->disconnectFromHost(); + if (!RMAPReceive_SOCKET->isOpen()) RMAPReceive_SOCKET->disconnectFromHost(); + if (!GRESBStatusQuery_SOCKET->isOpen()) GRESBStatusQuery_SOCKET->disconnectFromHost(); +} + +unsigned int rmapplugin::Write(unsigned int *Value, unsigned int count, unsigned int address) +{ + unsigned int remainingCount = count; + unsigned int iOffset = 0; + QString console_message; + char* data; + + unsigned char command = 0x08; // initialize command at 0b00001000 for write + + if(spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) + { + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** RMAP request already running, WRITE access stopped"); + return 1; + } + if (UI->RMAP_write_verify->isChecked()) command = command + (1<<2); + if (UI->RMAP_write_reply->isChecked()) command = command + (1<<1); + + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: unavailable"); + + data = (char*) malloc(READ_WRITE_MAX_COUNTS*4); + + APPENDTOLOG(QString("*** START *** WRITE ")+ QString::number(count) + QString(" word(s) @0x")+ QString::number(address,16)); + + while (remainingCount > READ_WRITE_MAX_COUNTS) + { + for (int i = 0; i>8); + data[i*4+1] = (char) ((unsigned int) Value[i+iOffset]>>16); + data[i*4+0] = (char) ((unsigned int) Value[i+iOffset]>>24); + } + + console_message.sprintf("remainingCount: %d => ", remainingCount); + APPENDTOLOG(console_message + QString("Write ")+ QString::number(READ_WRITE_MAX_COUNTS*4) + QString(" byte(s) @0x")+ QString::number(address,16)); + + if(WriteBLOCK(data, READ_WRITE_MAX_COUNTS*4, address)==0) + { + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** RMAP write command failed"); + return 1; + } + + remainingCount = remainingCount - READ_WRITE_MAX_COUNTS; + address = address + READ_WRITE_MAX_COUNTS * 4; + iOffset = iOffset + READ_WRITE_MAX_COUNTS; + } + + if (remainingCount > 0) + { + for (unsigned int i = 0; i>8); + data[i*4+1] = (char) ((unsigned int) Value[i+iOffset]>>16); + data[i*4+0] = (char) ((unsigned int) Value[i+iOffset]>>24); + } + + console_message.sprintf("remainingCount: %d => ", remainingCount); + APPENDTOLOG(console_message + QString("Write ")+ QString::number(remainingCount*4) + QString(" byte(s) @0x")+ QString::number(address,16)); + + if (WriteBLOCK(data, remainingCount*4, address)==0) + { + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** RMAP write command failed"); + return 1; + } + } + + APPENDTOLOG(QString("*** STOP *** WRITE")); + free(data); + return count; +} + +unsigned int rmapplugin::Read(unsigned int *Value, unsigned int count, unsigned int address) +{ + unsigned int remainingCount = count; + unsigned int iOffset = 0; + QString console_message; + + if(spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) + { + APPENDTOLOG("WARNING === in function READ of rmapplugin *** RMAP request already running, READ access stopped"); + return 1; + } + APPENDTOLOG(QString("*** START *** READ ")+ QString::number(count) + QString(" word(s) @0x")+ QString::number(address,16)); + + while (remainingCount > READ_WRITE_MAX_COUNTS) + { + console_message.sprintf("remainingCount: %d => ", remainingCount); + APPENDTOLOG(console_message + QString("Read ")+ QString::number(4*READ_WRITE_MAX_COUNTS) + QString(" byte(s) @0x")+ QString::number(address,16)); + + if (ReadBLOCK(READ_WRITE_MAX_COUNTS*4, address)==0) + { + APPENDTOLOG("WARNING === in function READ of rmapplugin *** RMAP packet not received"); + return 1; + } + + for(int i=0;irmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH]; + for(int j=1;j<4;j++) + { + Value[i+iOffset]= ((unsigned char)(spwPacketReceiverOBJECT->rmapPacket[i*4+j+RMAP_READ_REPLY_HEADER_LENGTH])) + Value[i+iOffset]*256; + } + } + + remainingCount = remainingCount - READ_WRITE_MAX_COUNTS; + address = address + READ_WRITE_MAX_COUNTS * 4; + iOffset = iOffset + READ_WRITE_MAX_COUNTS; + spwPacketReceiverOBJECT->acquireRMAPSemaphore(); + } + + if (remainingCount > 0) + { + console_message.sprintf("remainingCount: %d => ", remainingCount); + APPENDTOLOG(console_message + QString("Read ")+ QString::number(4*remainingCount) + QString(" byte(s) @0x")+ QString::number(address,16)); + + if (ReadBLOCK(4*remainingCount, address)==0) + { + APPENDTOLOG("WARNING === in function READ of rmapplugin *** RMAP packet not received"); + return 1; + } + + for(unsigned int i=0;irmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH]; + for(int j=1;j<4;j++) + { + Value[i+iOffset]= ((unsigned char)(spwPacketReceiverOBJECT->rmapPacket[i*4+j+RMAP_READ_REPLY_HEADER_LENGTH])) + Value[i+iOffset]*256; + } + } + spwPacketReceiverOBJECT->acquireRMAPSemaphore(); + } + + APPENDTOLOG(QString("*** STOP *** READ ")); + return count; +} + +unsigned int rmapplugin::ReadBLOCK(unsigned int nbBytes, unsigned int address) +{ + int errorCode; + RMAP *RMAPCommand; + QTime RMAPTimeout; + unsigned int dataLength; + if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) + { + RMAP_DISCONNECT(); + return 1; + } + + if (nbBytes > 4) + { + RMAPCommand = new RMAP(read_Inc, + UI->rmapTargetLogicalAddressSpinBox->value(), + UI->rmapSourceLogicalAddressSpinBox->value(), + address, + nbBytes, + NULL); + } + else + { + RMAPCommand = new RMAP(read_Single, + UI->rmapTargetLogicalAddressSpinBox->value(), + UI->rmapSourceLogicalAddressSpinBox->value(), + address, + nbBytes, + NULL); + } + + // SEND THE GRESB HEADER FOR THE RMAP READ COMMAND + RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->GRESBHeader), 4); + // SEND THE SPACEWIRE PACKET FOR THE RMAP READ COMMAND + RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->RMAPHeader), sizeof(RMAPCommand->RMAPHeader)); + RMAPSend_SOCKET->waitForBytesWritten(100); + RMAPTimeout.start(); + // write timeout + while(RMAPSend_SOCKET->bytesToWrite() > 0) + { + RMAPSend_SOCKET->waitForBytesWritten(100); + if(RMAPTimeout.elapsed()>1000) + { + APPENDTOLOG("WARNING === in function READ of rmapplugin *** sending Read RMAP Command timeout\n"); + return 0; + } + } + + // RECEIVE THE INCOMING RMAP PACKET + errorCode = spwPacketReceiverOBJECT->receiveSPWPacket(1); // request ID 1 is for RMAP packet + if (errorCode<=0) + { + APPENDTOLOG("WARNING === in function ReadBLOCK of rmapplugin *** RMAP packet reception failed with code " + QString::number(errorCode)); + return 0; + } + dataLength = spwPacketReceiverOBJECT->rmapPacketSize - RMAP_READ_REPLY_HEADER_LENGTH - RMAP_DATA_CRC_LENGTH; + if(dataLength != nbBytes) + { + APPENDTOLOG("WARNING === in function READ of rmapplugin *** number of data received (" + +QString::number(dataLength) + +") not equal to number of data requested (" + +QString::number(READ_WRITE_MAX_COUNTS*4) + +")"); + return 0; + } + return dataLength; +} + +unsigned int rmapplugin::WriteBLOCK(char *data, unsigned int nbBytes, unsigned int address) +{ + QTime RMAPTimeout; + RMAP *RMAPCommand; + int errorCode; + QString console_message; + + if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) + { + RMAP_DISCONNECT(); + return 1; + } + + RMAPCommand = new RMAP(UI->getCommandCode(), + UI->rmapTargetLogicalAddressSpinBox->value(), + UI->rmapSourceLogicalAddressSpinBox->value(), + address, + nbBytes, + data); + + // SEND GRESB HEADER + RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->GRESBHeader), 4); + // SEND SPACEWIRE PACKET HEADER + RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->RMAPHeader), sizeof(RMAPCommand->RMAPHeader)); + // SEND DATA + RMAPSend_SOCKET->write( data, nbBytes); + // SEND DATA CRC + RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->dataCRC), 1); + RMAPTimeout.start(); + while(RMAPSend_SOCKET->bytesToWrite() > 0) + { + RMAPSend_SOCKET->waitForBytesWritten(100); + if(RMAPTimeout.elapsed()>1000) + { + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** sending Write RMAP Command timeout"); + return 0; + } + } + + if (UI->RMAP_write_reply->isChecked()) + { + // WAIT FOR THE RMAP REPLY PACKET + errorCode = spwPacketReceiverOBJECT->receiveSPWPacket(1); + if (errorCode<=0) + { + APPENDTOLOG("WARNING === in function WriteBLOCK of rmapplugin *** RMAP packet reception failed with code " + QString::number(errorCode)); + return 0; + } + if(spwPacketReceiverOBJECT->rmapPacketSize != 8) + { + console_message.sprintf("WARNING === in function WRITE (with reply) of rmapplugin *** write reply format not compliant\n"); + APPENDTOLOG(console_message); + return 0; + } + switch (spwPacketReceiverOBJECT->rmapPacket[3]) // byte 4 is the status byte in the reply + { + case 0: + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 0 Successfull"); + break; + case 1: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** General error code"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 1 General error code"); + break; + case 2: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Unused RMAP packet type or command code"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 2 Unused RMAP packet type or command code"); + break; + case 3: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid key"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 3 Invalid key"); + break; + case 4: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid data CRC"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 4 Invalid data CRC"); + break; + case 5: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Early EOP"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 5 Early EOP"); + break; + case 6: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Too much data"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 6 Too much data"); + break; + case 7: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** EEP"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 7 EEP"); + break; + case 8: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Reserved"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 8 Reserved"); + break; + case 9: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Verify buffer overrun"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 9 Verify buffer overrun"); + break; + case 10: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** RMAP command not implemented or not authorised"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 10 RMAP command not implemented or not authorised"); + break; + case 11: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** RMW data length error"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 11 RMAP RMW data length error"); + break; + case 12: + APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid target logical address"); + UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 12 Invalid target logical address"); + break; + } + spwPacketReceiverOBJECT->acquireRMAPSemaphore(); + } + return nbBytes; +} + +//////// +// SLOTS + +unsigned int rmapplugin::WriteSPW(char *Value, unsigned int count, char targetLogicalAddress, char userApplication) // SLOT +{ + char protocoleIdentifier = 0x02; + char reserved = 0x00; + char gresbProtocole = 0x00; + unsigned char size[3]; + unsigned int spwPacketSize = count + 4; + QTime SPWTimeout; + + if (count>248) + { + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** CCSDS packet size > 248 bytes\n"); + return 1; + } + + APPENDTOLOG(QString("*** START *** Send CCSDS packet of ")+ QString::number(count) + QString(" byte(s)")); + + if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) + { + RMAP_DISCONNECT(); + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** SPW link not running\n"); + return 1; + } + + // SEND GRESB HEADER + size[0] = (unsigned char) ((unsigned int) spwPacketSize>>16); + size[1] = (unsigned char) ((unsigned int) spwPacketSize>>8); + size[2] = (unsigned char) ((unsigned int) spwPacketSize); + RMAPSend_SOCKET->write(&gresbProtocole, 1); + RMAPSend_SOCKET->write((char*) size, 3); + // SEND SPW HEADER + RMAPSend_SOCKET->write(&targetLogicalAddress, 1); + RMAPSend_SOCKET->write(&protocoleIdentifier, 1); + RMAPSend_SOCKET->write(&reserved, 1); + RMAPSend_SOCKET->write(&userApplication, 1); + // SEND CCSDS PACKET + RMAPSend_SOCKET->write(Value, count); + SPWTimeout.start(); + while(RMAPSend_SOCKET->bytesToWrite() > 0) + { + RMAPSend_SOCKET->waitForBytesWritten(100); + if(SPWTimeout.elapsed()>1000) + { + APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** sending CCSDS packet timeout\n"); + return 1; + } + } + + APPENDTOLOG(QString("*** CCSDS packet sent")); + + return count; +} + +void rmapplugin::sendCCSDS() // SLOT +{ + unsigned int nbBYTES_application_data = 8; + unsigned int count; + char *tab; + unsigned char packetErrorControl1 = 0xaa; + unsigned char packetErrorControl0 = 0xbb; + + ccsds_command = new ccsds(1, 0, 0, nbBYTES_application_data+12, 0, 0, 0, 0, 0); // +12 => packet header 6 bytes + data field header 4 bytes + packet error control 2 bytes + /* unsigned char data_field_header, + unsigned char processID, + unsigned int sequence_count, + unsigned int packet_length, + unsigned char acceptance, + unsigned int completion, + unsigned char service_type, + unsigned char service_subtype, + unsigned char sourceID*/ + + count = nbBYTES_application_data+12; // 12 is the size in bytes of the header + tab = (char*) malloc(count); + tab[0] = ccsds_command->ccsds_header->packetId1; + tab[1] = ccsds_command->ccsds_header->packetId0; + tab[2] = ccsds_command->ccsds_header->packetSequenceControl1; + tab[3] = ccsds_command->ccsds_header->packetSequenceControl0; + tab[4] = ccsds_command->ccsds_header->packetLength1; + tab[5] = ccsds_command->ccsds_header->packetLength0; + tab[6] = ccsds_command->ccsds_header->dataFieldHeader3; + tab[7] = ccsds_command->ccsds_header->dataFieldHeader2; + tab[8] = ccsds_command->ccsds_header->dataFieldHeader1; + tab[9] = ccsds_command->ccsds_header->dataFieldHeader0; + tab[10]=0x00; + tab[11]=0x00; + tab[12]=0x00; + tab[13]=0x00; + tab[14]=0x00; + tab[15]=0x00; + tab[nbBYTES_application_data+10] = packetErrorControl1; + tab[nbBYTES_application_data+11] = packetErrorControl0; + + WriteSPW(tab, count, UI->CCSDSTargetLogicalAddressSpinBox->value(), 0x00); + + free(tab); +} + +void rmapplugin::send_TC_LFR_UPDATE_TIME() +{ + unsigned int nbBYTES_application_data = 6; // Time at CUC format is on 48 bits / 6 bytes + unsigned int count; + char *tab; + unsigned char packetErrorControl1 = 0xaa; + unsigned char packetErrorControl0 = 0xbb; + + ccsds_command = new ccsds(1, 11, 0, nbBYTES_application_data, 1, 1, 9, 129, 0); + /* unsigned char data_field_header, + unsigned char processID, + unsigned int sequence_count, + unsigned int packet_length, + unsigned char acceptance, + unsigned int completion, + unsigned char service_type, + unsigned char service_subtype, + unsigned char sourceID*/ + + count = nbBYTES_application_data+12; // +12 => packet header 6 bytes + data field header 4 bytes + packet error control 2 bytes + tab = (char*) malloc(count); + tab[0] = ccsds_command->ccsds_header->packetId1; + tab[1] = ccsds_command->ccsds_header->packetId0; + tab[2] = ccsds_command->ccsds_header->packetSequenceControl1; + tab[3] = ccsds_command->ccsds_header->packetSequenceControl0; + tab[4] = ccsds_command->ccsds_header->packetLength1; + tab[5] = ccsds_command->ccsds_header->packetLength0; + tab[6] = ccsds_command->ccsds_header->dataFieldHeader3; + tab[7] = ccsds_command->ccsds_header->dataFieldHeader2; + tab[8] = ccsds_command->ccsds_header->dataFieldHeader1; + tab[9] = ccsds_command->ccsds_header->dataFieldHeader0; + tab[10] = (unsigned char) (time_COARSE>>24); + tab[11] = (unsigned char) (time_COARSE>>18); + tab[12] = (unsigned char) (time_COARSE>>8); + tab[13] = (unsigned char) (time_COARSE); + tab[14] = (unsigned char) (time_FINE>>8); + tab[15] = (unsigned char) (time_FINE); + tab[nbBYTES_application_data+10] = packetErrorControl1; + tab[nbBYTES_application_data+11] = packetErrorControl0; + + WriteSPW(tab, count, UI->CCSDSTargetLogicalAddressSpinBox->value(), 0x00); + + time_COARSE = time_COARSE+1; + + free(tab); +} + +void rmapplugin::reset_TC_LFR_UPDATE_TIME() +{ + time_COARSE = 0; + time_FINE = 0; +} + +void rmapplugin::RMAP_CONNECT() // SLOT +{ + bool spwRunning = true; + RMAPSend_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), + 3000 + UI->gresbVirtualLinkSpinBox->value()*2, + QIODevice::WriteOnly); + RMAPReceive_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), + 3000 + UI->gresbVirtualLinkSpinBox->value()*2+1, + QIODevice::ReadOnly); + GRESBStatusQuery_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), + 3010, + QIODevice::ReadWrite); + GRESBStatusQuery_SOCKET->waitForConnected(10000); + RMAPReceive_SOCKET->readAll(); // read all remaining data from the reception socket + // initialize SPW packet semaphores + while (spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->acquire(); + while (spwPacketReceiverOBJECT->ccsdsPacketSEMAPHORE->available()!=0) spwPacketReceiverOBJECT->ccsdsPacketSEMAPHORE->acquire(); + if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) != 0) + { + spwRunning = UI->gresbStatusQueryDialog->exec(); + } + if (spwRunning == false) RMAP_DISCONNECT(); + else + { + APPENDTOLOG(QString("SpaceWire running on virtual link ")+ QString::number(UI->spwLinkSpinBox->value())); + emit this->activateSig(true); + } +} + +void rmapplugin::RMAP_DISCONNECT() // SLOT +{ + RMAPSend_SOCKET->disconnectFromHost(); + RMAPReceive_SOCKET->disconnectFromHost(); + GRESBStatusQuery_SOCKET->disconnectFromHost(); + emit this->activateSig(false); +} + +void rmapplugin::RMAPSendConnectionState(QAbstractSocket::SocketState socketState) // SLOT +{ + UI->rmapSendStateLabel->setText(""); + QString socketMessage = "RMAP Send Socket State: "; + switch(socketState) + { + case QAbstractSocket::UnconnectedState : + socketMessage.append("0 => Unconnected"); + UI->rmapOpenCommunicationButton->setEnabled(true); + UI->rmapCloseCommunicationButton->setEnabled(false); + emit this->activateSig(false); + break; + case 1: + socketMessage.append("1 => HostLookup"); + break; + case 2: + socketMessage.append("2 => Connecting"); + break; + case 3: + socketMessage.append("3 => Connected"); + UI->rmapOpenCommunicationButton->setEnabled(false); + UI->rmapCloseCommunicationButton->setEnabled(true); + break; + case 4: + socketMessage.append("4 => Bound"); + break; + case 5: + socketMessage.append("5 => Closing"); + break; + case 6: + socketMessage.append("6 => Listening"); + break; + } + UI->rmapSendStateLabel->setText(socketMessage); + APPENDTOLOG(socketMessage); +} + +void rmapplugin::RMAPReceiveConnectionState(QAbstractSocket::SocketState socketState) // SLOT +{ + UI->rmapReceiveStateLabel->setText(""); + QString socketMessage = "RMAP Receive Socket State: "; + switch(socketState) + { + case QAbstractSocket::UnconnectedState : + socketMessage.append("0 => Unconnected"); + break; + case 1: + socketMessage.append("1 => HostLookup"); + break; + case 2: + socketMessage.append("2 => Connecting"); + break; + case 3: + socketMessage.append("3 => Connected"); + break; + case 4: + socketMessage.append("4 => Bound"); + break; + case 5: + socketMessage.append("5 => Closing"); + break; + case 6: + socketMessage.append("6 => Listening"); + break; + } + UI->rmapReceiveStateLabel->setText(socketMessage); + APPENDTOLOG(socketMessage); +} + +void rmapplugin::GRESBConnectionState(QAbstractSocket::SocketState socketState) // SLOT +{ + UI->gresbStatusQueryLabel->setText(""); + QString socketMessage = "GRESB status query socket (port 3010): "; + switch(socketState) + { + case QAbstractSocket::UnconnectedState : + socketMessage.append("0 => Unconnected"); + break; + case 1: + socketMessage.append("1 => HostLookup"); + break; + case 2: + socketMessage.append("2 => Connecting"); + break; + case 3: + socketMessage.append("3 => Connected"); + break; + case 4: + socketMessage.append("4 => Bound"); + break; + case 5: + socketMessage.append("5 => Closing"); + break; + case 6: + socketMessage.append("6 => Listening"); + break; + } + UI->gresbStatusQueryLabel->setText(socketMessage); +} + +void rmapplugin::reTestSPWLink() // SLOT +{ + if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 0) + { + UI->gresbStatusQueryDialog->accept(); + } +} + +int rmapplugin::GRESBStatusQuery() // SLOT +{ + GRESBStatusQueryRequest(LinkStatus, 0); + GRESBStatusQueryRequest(LinkStatus, 1); + GRESBStatusQueryRequest(LinkStatus, 2); + GRESBStatusQueryRequest(LinkStatistics, 0); + GRESBStatusQueryRequest(LinkStatistics, 1); + GRESBStatusQueryRequest(LinkStatistics, 2); + return 0; +} + +void rmapplugin::displayOnConsole(QString message) +{ + this->UI->console->append(message); +} + +///////////////////// +// INTERNAL FUNCTIONS + +int rmapplugin::GRESBStatusQueryRequest(GresbStatusQueryOption option, char link) +{ + gresb_status_query_t statusQueryCommand; + gresb_link_status_reply_t linkStatusReply; + gresb_link_statistics_reply_t linkStatisticsReply; + QTime statusQueryTimeout; + QString console_message; + + statusQueryCommand.protocolIdentifier = (char) 0x02; + statusQueryCommand.reserved1 = (char) 0x00; + statusQueryCommand.reserved0 = (char) 0x00; + statusQueryCommand.option = (char) option; + statusQueryCommand.value3 = (char) 0x00; + statusQueryCommand.value2 = (char) 0x00; + statusQueryCommand.value1 = (char) 0x00; + statusQueryCommand.value0 = (char) link; + + GRESBStatusQuery_SOCKET->write((char*) ((void*) &statusQueryCommand), sizeof(statusQueryCommand)); + GRESBStatusQuery_SOCKET->flush(); + GRESBStatusQuery_SOCKET->waitForBytesWritten(1000); + + statusQueryTimeout.start(); + while(GRESBStatusQuery_SOCKET->bytesToWrite() > 0) + { + GRESBStatusQuery_SOCKET->waitForBytesWritten(100); + if(statusQueryTimeout.elapsed()>1000) + { + APPENDTOLOG("WARNING === in function GRESBStatusQueryRequest of rmapplugin *** sending StatusQueryCommand timeout"); + return 1; + } + } + + switch (option) + { + case LinkStatus: + { + statusQueryTimeout.start(); + while(GRESBStatusQuery_SOCKET->bytesAvailable() < (int) sizeof(linkStatusReply)) + { + GRESBStatusQuery_SOCKET->waitForReadyRead(100); + if(statusQueryTimeout.elapsed()>1000) + { + console_message.sprintf("GRESBStatusQueryRequest / LinkStatus => error timeout bytesAvailable()\n"); + APPENDTOLOG(console_message); + return 1; + } + } + GRESBStatusQuery_SOCKET->read((char*) ((void*) &linkStatusReply), (int) sizeof(linkStatusReply)); + console_message.sprintf("%x", linkStatusReply.byte0); + UI->spwLinkStatusEnquiry->statusQueryTable->item(0, link)->setText(console_message); + console_message.sprintf("%d", linkStatusReply.byte1); + UI->spwLinkStatusEnquiry->statusQueryTable->item(1, link)->setText(console_message); + if (linkStatusReply.byte0 == 0) return 1; + break; + } + case LinkStatistics: + { + statusQueryTimeout.start(); + while(GRESBStatusQuery_SOCKET->bytesAvailable() < (int) sizeof(linkStatisticsReply)) + { + GRESBStatusQuery_SOCKET->waitForReadyRead(100); + if(statusQueryTimeout.elapsed()>1000) + { + console_message.sprintf("GRESBStatusQueryRequest / LinkStatistics => error timeout bytesAvailable()\n"); + APPENDTOLOG(console_message); + return 1; + } + } + GRESBStatusQuery_SOCKET->read((char*) ((void*) &linkStatisticsReply), sizeof(linkStatisticsReply)); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.sizeOfDataTransmitted)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(9, link)->setText(console_message); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsTransmitted)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(8, link)->setText(console_message); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfTruncatedPacketsReceived)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(6, link)->setText(console_message); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsWithEEPReceived)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(5, link)->setText(console_message); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.sizeOfDataReceived)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(4, link)->setText(console_message); + console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsReceived)); + UI->spwLinkStatusEnquiry->statusQueryTable->item(3, link)->setText(console_message); + break; + } + case NodeAddressStatistics: + { + break; + } + case GetRoute: + { + break; + } + } + return 0; +} + +int rmapplugin::charTab_TO_int(char *charTab) +{ + int result = 0; + result = (charTab[0]<<24) +(charTab[1]<<16) +(charTab[2]<<8) + charTab[3]; + return result; +} + diff --git a/rmapplugin/rmapplugin.h b/rmapplugin/rmapplugin.h new file mode 100755 --- /dev/null +++ b/rmapplugin/rmapplugin.h @@ -0,0 +1,95 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the LPPMON Software +-- Copyright (C) 2011, Laboratory of Plasmas Physic - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@lpp.polytechnique.fr +----------------------------------------------------------------------------*/ +#ifndef DRIVER1_H +#define DRIVER1_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define APPENDTOLOG(message) this->UI->appendToLogFile(QTime::currentTime().toString() +":" + QString::number(QTime::currentTime().msec()) + ": " + message) + +#define READ_WRITE_MAX_COUNTS 4096 // in words +#define RMAP_MAX_DATA_LENGTH 4*READ_WRITE_MAX_COUNTS // in bytes, shall be lower than the limit size of SPW packet of the GRESB bridge +#define RMAP_READ_REPLY_HEADER_LENGTH 12 // in bytes => ECSS +#define RMAP_READ_COMMAND_HEADER_LENGTH 16 // in bytes => ECSS +#define RMAP_DATA_CRC_LENGTH 1 // in bytes => ECSS +#define CCSDS_MAX_PACKET_LENGTH 4412 // in bytes, specified in the LFR Software Requirements Specification + +class rmapplugin : public lppmonplugin +{ + Q_OBJECT +public: + explicit rmapplugin(QWidget *parent = 0); + ~rmapplugin(); + int GRESBStatusQueryRequest(GresbStatusQueryOption option, char link); + int charTab_TO_int(char *charTab); + +public slots: + unsigned int Write(unsigned int *Value,unsigned int count,unsigned int address=0); + unsigned int Read(unsigned int *Value,unsigned int count,unsigned int address=0); + // + unsigned int WriteSPW(char *Value, unsigned int count, char targetLogicalAddress, char userApplication); + void sendCCSDS(); + void send_TC_LFR_UPDATE_TIME(); + void reset_TC_LFR_UPDATE_TIME(); + int GRESBStatusQuery(); + void displayOnConsole(QString message); + // + void RMAP_CONNECT(); + void RMAP_DISCONNECT(); + int RMAPSendReadCommand(); + int RMAPSendWriteCommand(); + void reTestSPWLink(); + // + void RMAPSendConnectionState(QAbstractSocket::SocketState socketState); + void RMAPReceiveConnectionState(QAbstractSocket::SocketState socketState); + void GRESBConnectionState(QAbstractSocket::SocketState socketState); + +signals: + void ccsdsPacketReadyRead(char *ccsdsPacket, unsigned int size); + +private: + rmapPluginUI* UI; + QTcpSocket* GRESBStatusQuery_SOCKET; + QTcpSocket* RMAPSend_SOCKET; + QTcpSocket* RMAPReceive_SOCKET; + ccsds* ccsds_command; + unsigned int rmapPacketSize; + unsigned int time_COARSE; + unsigned int time_FINE; + spwpacketreceiver* spwPacketReceiverOBJECT; + unsigned int WriteBLOCK(char *data,unsigned int nbBytes,unsigned int address=0); + unsigned int ReadBLOCK(unsigned int nbBytes,unsigned int address=0); + char timeCode; +}; + +#endif // DRIVER1_H diff --git a/rmapplugin/rmapplugin.pro b/rmapplugin/rmapplugin.pro new file mode 100755 --- /dev/null +++ b/rmapplugin/rmapplugin.pro @@ -0,0 +1,69 @@ +# +# Project created by QtCreator 2011-09-20T08:15:30 +# +#------------------------------------------------- + +#include(/etc/lppmon/lppmonplugin.prf) +CONFIG += lppmonplugin +TARGET = rmapplugin + +DEFINES += PLUGIN=rmapplugin +DEFINES += PLUGINHEADER="\"\\\"rmapplugin.h"\\\"\" +DEFINES += driver_Name="\"\\\"RMAPPlugin"\\\"\" +DEFINES += driver_Author="\"\\\"Paul Leroy paul.leroy@lpp.polytechnique.fr"\\\"\" +DEFINES += driver_Version="\"\\\"1.1.2"\\\"\" +DEFINES += driver_Description="\"\\\"AHB bus controler, works with Gaisler's AHB plugn' play bus."\\\"\" +DEFINES += driver_can_be_root=1 +DEFINES += driver_can_be_child=0 +DEFINES += driver_VID=0 +DEFINES += driver_PID=0 + + +QT += network + + +LIBS += ../spw_usb_driver_v2.61/lib/libSpaceWireUSBAPI.so + + +INCLUDEPATH += \ + $${PWD} \ + ../common_PLE \ + ../spw_usb_driver_v2.61/inc + + +HEADERS += \ + rmappluginui.h \ + rmapplugin.h \ + rmapoperations.h \ + ccsds.h \ + spwpacketreceiver.h \ + ../common_PLE/qipdialogbox.h \ + ../common_PLE/gresbstatusenquiry.h \ + spectralmatricesdmasimulator.h \ + rmappluginpythonwrapper.h \ + stardundee.h \ + ../spw_usb_driver_v2.61/inc/spw_usb_api.h + + +SOURCES += \ + rmapplugin.cpp \ + rmappluginui.cpp \ + rmapoperations.cpp \ + ccsds.cpp \ + spwpacketreceiver.cpp \ + ../common_PLE/qipdialogbox.cpp \ + ../common_PLE/gresbstatusenquiry.cpp \ + spectralmatricesdmasimulator.cpp \ + rmappluginpythonwrapper.cpp \ + stardundee.cpp + + + + + + + + + + + diff --git a/rmapplugin/rmappluginpythonwrapper.cpp b/rmapplugin/rmappluginpythonwrapper.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/rmappluginpythonwrapper.cpp @@ -0,0 +1,19 @@ +#include "rmappluginpythonwrapper.h" +#include + +rmappluginPythonWrapper::rmappluginPythonWrapper(QObject *parent) : + genericPySysdriver(parent) +{ +} + + +QList rmappluginPythonWrapper::getData() +{ + QList data; + for (int i = 0; i<1024; i++) + { + QVariant t(1000*cos(0.1*i)); + data.append(t); + } + return data; +} diff --git a/rmapplugin/rmappluginpythonwrapper.h b/rmapplugin/rmappluginpythonwrapper.h new file mode 100755 --- /dev/null +++ b/rmapplugin/rmappluginpythonwrapper.h @@ -0,0 +1,22 @@ +#ifndef RMAPPLUGINPYTHONWRAPPER_H +#define RMAPPLUGINPYTHONWRAPPER_H + +#include +#include +#include +#include + +class rmappluginPythonWrapper : public genericPySysdriver +{ + Q_OBJECT +public: + explicit rmappluginPythonWrapper(QObject *parent = 0); + +signals: + +public slots: + QList getData(); + +}; + +#endif // RMAPPLUGINPYTHONWRAPPER_H diff --git a/rmapplugin/rmappluginui.cpp b/rmapplugin/rmappluginui.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/rmappluginui.cpp @@ -0,0 +1,240 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the LPPMON Software +-- Copyright (C) 2011, Laboratory of Plasmas Physic - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@lpp.polytechnique.fr +----------------------------------------------------------------------------*/ +#include "rmapplugin.h" + +rmapPluginUI::rmapPluginUI(QWidget *parent) : + QWidget(parent) +{ + spectralMatricesDMASimulator = new SpectralMatricesDMASimulator; + spwTabWidget = new QTabWidget; + QWidget* spwTabWidgetPage0 = new QWidget; + QWidget* spwTabWidgetPage1 = new QWidget; + QWidget* spwTabWidgetPage2 = new QWidget; + QWidget* spwTabWidgetPage3 = new QWidget; + QWidget* spwTabWidgetPage4 = new QWidget; + QWidget* spwTabWidgetPage5 = new QWidget; + mainLayout = new QVBoxLayout; + connectionLayout = new QGridLayout; + ccsdsLayout = new QVBoxLayout; + consoleLayout = new QVBoxLayout; + + //*** QLABEL ***// + gresbBridgeIPLabel = new QLabel(tr("GRESB Bridge IP: ")); + gresbVirtualLinkLabel = new QLabel(tr("GRESB Virtual Link: ")); + spwLinkLabel = new QLabel(tr("GRESB SPW Link: ")); + rmapSourceLogicalAddressLabel = new QLabel(tr("RMAP Source Logical Address: ")); + rmapTargetLogicalAddressLabel = new QLabel(tr("RMAP Target Logical Address: ")); + rmapSendStateLabel = new QLabel(tr("RMAP Send Socket State: waiting for connection")); + rmapReceiveStateLabel = new QLabel(tr("RMAP Receive Socket State: waiting for connection")); + logFileName = new QLabel; + gresbStatusQueryLabel = new QLabel(tr("GRESB status query socket (port 3010): waiting for connection")); + gresbStatusQueryDialogLabel = new QLabel(tr("sockets opened but SpaceWire link not running")); + sendCCSDSCommandLabel = new QLabel(tr("Address of the target")); + + //*** QPUSHBUTTON ***// + rmapOpenCommunicationButton = new QPushButton(tr("Open RMAP Communication")); + rmapCloseCommunicationButton = new QPushButton(tr("Close RMAP Communication")); + rmapCloseCommunicationButton->setEnabled(false); + logFileChooseButton = new QPushButton(tr("Choose file")); + gresbStatusQueryRetryButton = new QPushButton(tr("Retry")); + gresbStatusQueryAbortButton = new QPushButton(tr("Abort")); + sendCCSDSCommandButton = new QPushButton(tr("Send CCSDS Command")); + send_TC_LFR_UPDATE_TIME_Button = new QPushButton(tr("Send TC_LFR_UPDATE_TIME Packet")); + reset_TC_LFR_UPDATE_TIME_Button = new QPushButton(tr("reset the TC_LFR_UPDATE_TIME Packet coarse and fine times")); + clearConsoleButton = new QPushButton(tr("Clear")); + + //*** SPINBOX ***// + gresbVirtualLinkSpinBox = new QSpinBox; + rmapSourceLogicalAddressSpinBox = new QSpinBox; + rmapTargetLogicalAddressSpinBox = new QSpinBox; + spwLinkSpinBox = new QSpinBox;; + CCSDSTargetLogicalAddressSpinBox = new QSpinBox; + gresbVirtualLinkSpinBox->setRange(0, 4); + gresbVirtualLinkSpinBox->setValue(1); + rmapSourceLogicalAddressSpinBox->setRange(0, 255); + rmapSourceLogicalAddressSpinBox->setValue(33); + rmapTargetLogicalAddressSpinBox->setRange(0, 255); + rmapTargetLogicalAddressSpinBox->setValue(254); + spwLinkSpinBox->setRange(0, 2); + spwLinkSpinBox->setValue(0); + CCSDSTargetLogicalAddressSpinBox->setRange(0,255); + CCSDSTargetLogicalAddressSpinBox->setValue(254); + + //*** MISC **// + starDundee = new StarDundee; + console = new QTextEdit; + gresbBridgeIPDialogBox = new QIPDialogBox; + gresbStatusQueryDialog = new QDialog; + logEnableCheckBox = new QCheckBox(tr("Enable Logs")); + RMAP_write_verify = new QCheckBox(tr("data checked before write\nlimited to 4 bytes\nNOT IMPLEMENTED")); + RMAP_write_reply = new QCheckBox(tr("reply to the write command required\nlast reply status: unavailable")); + spwLinkStatusEnquiry = new gresbStatusEnquiry; + logFile = new QFile(); + + logFileEn = false; + + connectionLayout->addWidget(gresbBridgeIPLabel, 0, 0, 0); + connectionLayout->addWidget(gresbBridgeIPDialogBox, 0, 1, 0); + connectionLayout->addWidget(gresbVirtualLinkLabel, 1, 0, 0); + connectionLayout->addWidget(gresbVirtualLinkSpinBox, 1, 1, 0); + connectionLayout->addWidget(rmapSourceLogicalAddressLabel, 2, 0, 0); + connectionLayout->addWidget(rmapSourceLogicalAddressSpinBox, 2, 1, 0); + connectionLayout->addWidget(spwLinkLabel, 3, 0, 0); + connectionLayout->addWidget(spwLinkSpinBox, 3, 1, 0); + connectionLayout->addWidget(rmapTargetLogicalAddressLabel, 4, 0, 0); + connectionLayout->addWidget(rmapTargetLogicalAddressSpinBox, 4, 1, 0); + connectionLayout->addWidget(rmapOpenCommunicationButton, 5, 0, 1, 2); + connectionLayout->addWidget(rmapCloseCommunicationButton, 6, 0, 1, 2); + connectionLayout->addWidget(rmapSendStateLabel, 7, 0, 1, 2); + connectionLayout->addWidget(rmapReceiveStateLabel, 8, 0, 1, 2); + connectionLayout->addWidget(gresbStatusQueryLabel, 9, 0, 1, 2); + connectionLayout->addWidget(logEnableCheckBox, 10, 0, 0); + connectionLayout->addWidget(logFileChooseButton, 10, 1, 0); + connectionLayout->addWidget(RMAP_write_verify, 11, 0, 1, 2); + connectionLayout->addWidget(RMAP_write_reply, 12, 0, 1, 2); + + connectionLayout->setRowStretch(13, 1); + connectionLayout->setColumnStretch(2, 1); + + ccsdsLayout->addWidget(sendCCSDSCommandButton); + ccsdsLayout->addWidget(send_TC_LFR_UPDATE_TIME_Button); + ccsdsLayout->addWidget(reset_TC_LFR_UPDATE_TIME_Button); + ccsdsLayout->addWidget(sendCCSDSCommandLabel); + ccsdsLayout->addWidget(CCSDSTargetLogicalAddressSpinBox); + + consoleLayout->addWidget(console); + consoleLayout->addWidget(clearConsoleButton); + + connect(this->logFileChooseButton, SIGNAL(clicked()), this, SLOT(chooseLogFile())); + connect(this, SIGNAL(setLogFileName(QString)), this->logFileName, SLOT(setText(QString))); + connect(this->logEnableCheckBox, SIGNAL(stateChanged(int)), this, SLOT(logFileEnDisable(int))); + + spwTabWidget->addTab(spwTabWidgetPage0, tr("connection")); + spwTabWidget->addTab(spwTabWidgetPage1, tr("ccsds")); + spwTabWidget->addTab(spwTabWidgetPage2, tr("status")); + spwTabWidget->addTab(spwTabWidgetPage3, tr("console")); + spwTabWidget->addTab(spwTabWidgetPage4, tr("DMA")); + spwTabWidget->addTab(spwTabWidgetPage5, tr("Star Dundee")); + spwTabWidgetPage0->setLayout(connectionLayout); + spwTabWidgetPage1->setLayout(ccsdsLayout); + spwTabWidgetPage2->setLayout(this->spwLinkStatusEnquiry->mainLayout); + spwTabWidgetPage3->setLayout(consoleLayout); + spwTabWidgetPage4->setLayout(spectralMatricesDMASimulator->mainLayout); + spwTabWidgetPage5->setLayout(starDundee->layout()); + mainLayout->addWidget(spwTabWidget); + setLayout(mainLayout); + + // GRESB STATUS QUERY DIALOG + gresbStatusQueryDialogLayout = new QGridLayout; + gresbStatusQueryDialogLayout->addWidget(gresbStatusQueryDialogLabel, 0, 0, 1, 2); + gresbStatusQueryDialogLayout->addWidget(gresbStatusQueryRetryButton, 1, 0, 0); + gresbStatusQueryDialogLayout->addWidget(gresbStatusQueryAbortButton, 1, 1, 0); + gresbStatusQueryDialog->setLayout(gresbStatusQueryDialogLayout); + + connect(gresbStatusQueryAbortButton, SIGNAL(clicked()), gresbStatusQueryDialog, SLOT(reject())); + connect(this->clearConsoleButton, SIGNAL(clicked()), this->console, SLOT(clear())); +} + +void rmapPluginUI::connectPort() +{ + //emit this->connectPortsig(ui->PortName->text(),ui->PortspeedSlider->value()); +} + +void rmapPluginUI::setConnected(bool connected) +{ + /*if(connected == true) + { + ui->OpenPort->setText(tr("Close port")); + } + else + ui->OpenPort->setText(tr("Open port"));*/ +} + + +rmapPluginUI::~rmapPluginUI() +{ + //delete ui; +} + +void rmapPluginUI::chooseLogFile() +{ + if(this->logFile->isOpen()) + this->logFile->close(); + this->logFile->setFileName(QFileDialog::getSaveFileName(this,tr("Open Log file"), + QDir::homePath() + + "/" + + QDate::currentDate().toString() + + "_" + + QTime::currentTime().toString() + + "_rmapPluginUI.log", + tr("Log Files (*.txt *.log)"))); + if(this->logFile->open(QIODevice::WriteOnly)) + { + this->logFileStrm = new QTextStream(this->logFile); + emit this->setLogFileName(this->logFile->fileName()); + } +} + +void rmapPluginUI::logFileEnDisable(int state) +{ + if(state==Qt::Checked) + { + this->logFileEn = true; + } + else if(state==Qt::Unchecked) + { + this->logFileEn = false; + } +} + +bool rmapPluginUI::islogfileenable() +{ + return this->logFileEn; +} + +void rmapPluginUI::appendToLogFile(const QString & text) +{ + if(this->logFileEn && this->logFile->isOpen()) + { + *(this->logFileStrm) << text << endl; + } +} + +void rmapPluginUI::closeEvent(QCloseEvent *event) +{ + if(this->logFile->isOpen()) + { + this->logFileStrm->flush(); + this->logFile->waitForBytesWritten(3000); + this->logFile->close(); + } + event->accept(); +} + +RMAP_command_codes rmapPluginUI::getCommandCode() +{ + if (RMAP_write_verify->isChecked() and RMAP_write_reply->isChecked()) return writeSingle_ver_rep; + if (RMAP_write_verify->isChecked() and !RMAP_write_reply->isChecked()) return writeSingle_ver_noRep; + if (!RMAP_write_verify->isChecked() and RMAP_write_reply->isChecked()) return writeSingle_noVer_Rep; + if (!RMAP_write_verify->isChecked() and !RMAP_write_reply->isChecked()) return writeSingle_noVer_noRep; + else return invalid0; +} diff --git a/rmapplugin/rmappluginui.h b/rmapplugin/rmappluginui.h new file mode 100755 --- /dev/null +++ b/rmapplugin/rmappluginui.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the LPPMON Software +-- Copyright (C) 20011, Laboratory of Plasma Physics - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Paul Leroy +-- Mail : paul.leroy@lpp.polytechnique.fr +----------------------------------------------------------------------------*/ +#ifndef RMAPPLUGINUI_H +#define RMAPPLUGINUI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qipdialogbox.h" +#include +#include +#include +#include "spectralmatricesdmasimulator.h" +#include + +class rmapPluginUI : public QWidget +{ + Q_OBJECT + +public: + explicit rmapPluginUI(QWidget *parent = 0); + ~rmapPluginUI(); + + QPushButton* rmapOpenCommunicationButton; + QPushButton* rmapCloseCommunicationButton; + QPushButton* logFileChooseButton; + QPushButton* gresbStatusQueryRetryButton; + QPushButton* gresbStatusQueryAbortButton; + QPushButton* sendCCSDSCommandButton; + QPushButton* send_TC_LFR_UPDATE_TIME_Button; + QPushButton* reset_TC_LFR_UPDATE_TIME_Button; + QPushButton* clearConsoleButton; + + QSpinBox* gresbVirtualLinkSpinBox; + QSpinBox* spwLinkSpinBox; + QSpinBox* rmapSourceLogicalAddressSpinBox; + QSpinBox* rmapTargetLogicalAddressSpinBox; + QSpinBox* CCSDSTargetLogicalAddressSpinBox; + + QIPDialogBox* gresbBridgeIPDialogBox; + + QCheckBox *logEnableCheckBox; + QCheckBox *RMAP_write_verify; + QCheckBox *RMAP_write_reply; + + QLabel* rmapSendStateLabel; + QLabel* rmapReceiveStateLabel; + QLabel* gresbStatusQueryLabel; + QLabel* gresbStatusQueryDialogLabel; + QLabel* sendCCSDSCommandLabel; + + QDialog* gresbStatusQueryDialog; + + gresbStatusEnquiry* spwLinkStatusEnquiry; + + SpectralMatricesDMASimulator *spectralMatricesDMASimulator; + + QTextEdit* console; + + StarDundee *starDundee; + + bool islogfileenable(); + void appendToLogFile(const QString & text); + void closeEvent(QCloseEvent *event); + RMAP_command_codes getCommandCode(); + +public slots: + void setConnected(bool connected); + void connectPort(); + void chooseLogFile(); + void logFileEnDisable(int state); + +signals: + void connectPortsig(QString PortName,int baudrate); + void setLogFileName(QString FileName); + +private: + QLabel* gresbBridgeIPLabel; + QLabel* gresbVirtualLinkLabel; + QLabel* spwLinkLabel; + QLabel* rmapSourceLogicalAddressLabel; + QLabel* rmapTargetLogicalAddressLabel; + QLabel *logFileName; + + QVBoxLayout* mainLayout; + QGridLayout* connectionLayout; + QVBoxLayout* ccsdsLayout; + QVBoxLayout* consoleLayout; + QGridLayout* gresbStatusQueryDialogLayout; + + QTabWidget* spwTabWidget; + + QFile* logFile; + QTextStream* logFileStrm; + bool logFileEn; + +}; + +#endif // RMAPPLUGINUI_H diff --git a/rmapplugin/spectralmatricesdmasimulator.cpp b/rmapplugin/spectralmatricesdmasimulator.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/spectralmatricesdmasimulator.cpp @@ -0,0 +1,133 @@ +#include "spectralmatricesdmasimulator.h" + +SpectralMatricesDMASimulator::SpectralMatricesDMASimulator(QWidget *parent) : + QWidget(parent) +{ + timer = new QTimer; + QString message; + count = SPECTRAL_MATRIX_SIZE; + unsigned int i = 0; + + Value = (unsigned int*) malloc(count*sizeof(int)); + for (i=0; iaddWidget(sendOneSpectralMatrix1Button); + mainLayout->addWidget(sendOneSpectralMatrix2Button); + mainLayout->addWidget(readMatrixAddress1Button); + mainLayout->addWidget(readMatrixAddress2Button); + mainLayout->addWidget(startSendingMatricesButton); + mainLayout->addWidget(stopSendingMatricesButton); + this->setLayout(mainLayout); + + message.append("Address of the Spectral Matrix N°1: " + QString::number(spectralMatrixAddress1)); + emit sendMessage(message); + message.append("Address of the Spectral Matrix N°2: " + QString::number(spectralMatrixAddress2)); + emit sendMessage(message); + + connect(this->sendOneSpectralMatrix1Button, SIGNAL(clicked()), this, SLOT(sendOneSpectralMatrix1SLOT())); + connect(this->sendOneSpectralMatrix2Button, SIGNAL(clicked()), this, SLOT(sendOneSpectralMatrix2SLOT())); + connect(this->readMatrixAddress1Button, SIGNAL(clicked()), this, SLOT(readMatrixAddress1SLOT())); + connect(this->readMatrixAddress2Button, SIGNAL(clicked()), this, SLOT(readMatrixAddress2SLOT())); + connect(this->timer, SIGNAL(timeout()), this, SLOT(sendOneSpectralMatrixSLOT())); + connect(this->startSendingMatricesButton, SIGNAL(clicked()), this, SLOT(startSendingMatricesSLOT())); + connect(this->stopSendingMatricesButton, SIGNAL(clicked()), this, SLOT(stopSendingMatricesSLOT())); +} + +void SpectralMatricesDMASimulator::sendOneSpectralMatrix1SLOT() +{ + emit(rmapplugginRead(&spectralMatrixAddress1, 1, APB_SPECTRAL_MATRICES_DMA1)); + emit(rmapplugginWrite(Value, count, spectralMatrixAddress1)); + emit(rmapplugginRead(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + spectralMatrixCTRL = spectralMatrixCTRL | 0x00000001; + emit(rmapplugginWrite(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + emit(rmapplugginWrite(&irqctrlForce, 1, APB_ADDRESS_IRQCTRL)); +} + +void SpectralMatricesDMASimulator::sendOneSpectralMatrix2SLOT() +{ + emit(rmapplugginRead(&spectralMatrixAddress2, 1, APB_SPECTRAL_MATRICES_DMA2)); + emit(rmapplugginWrite(Value, count, spectralMatrixAddress2)); + emit(rmapplugginRead(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + spectralMatrixCTRL = spectralMatrixCTRL | 0x00000002; + emit(rmapplugginWrite(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + emit(rmapplugginWrite(&irqctrlForce, 1, APB_ADDRESS_IRQCTRL)); +} + +void SpectralMatricesDMASimulator::sendOneSpectralMatrixSLOT() +{ + if (flagSendMatrix1 == true) + { + emit(rmapplugginRead(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + if ( (spectralMatrixCTRL & 1) == 1) emit(sendMessage("ERROR matrix 1 not processed")); + //emit(rmapplugginWrite(Value, count, spectralMatrixAddress1)); + spectralMatrixCTRL = spectralMatrixCTRL | 0x00000001; // sets the bit 0 of the ctrl register to 1 + emit(rmapplugginWrite(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + emit(rmapplugginWrite(&irqctrlForce, 1, APB_ADDRESS_IRQCTRL)); + flagSendMatrix1 = false; + nbMatricesSent++; + if (nbMatricesSent==400) { + emit(sendMessage("400 matrices successfully sent")); + nbMatricesSent = 0; + } + } + else if (flagSendMatrix1 == false) + { + emit(rmapplugginRead(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + if ( ( (spectralMatrixCTRL>>1) & 1 ) == 1 ) emit(sendMessage("ERROR matrix 2 not processed")); + //emit(rmapplugginWrite(Value, count, spectralMatrixAddress2)); + spectralMatrixCTRL = spectralMatrixCTRL | 0x00000002; // sets the bit 1 of the ctrl register to 1 + emit(rmapplugginWrite(&spectralMatrixCTRL, 1, APB_SPECTRAL_MATRICES_CTRL)); + emit(rmapplugginWrite(&irqctrlForce, 1, APB_ADDRESS_IRQCTRL)); + flagSendMatrix1 = true; + nbMatricesSent++; + if (nbMatricesSent==400) { + emit(sendMessage("400 matrices successfully sent")); + nbMatricesSent = 0; + } + } +} + +void SpectralMatricesDMASimulator::readMatrixAddress1SLOT() +{ + QString message; + emit(rmapplugginRead(&spectralMatrixAddress1, 1, APB_SPECTRAL_MATRICES_DMA1)); + message.append("Address of the Spectral Matrix (1): " + + QString::number(spectralMatrixAddress1, 16)); + emit sendMessage(message); +} + +void SpectralMatricesDMASimulator::readMatrixAddress2SLOT() +{ + QString message; + emit(rmapplugginRead(&spectralMatrixAddress2, 1, APB_SPECTRAL_MATRICES_DMA2)); + message.append("Address of the Spectral Matrix (2): " + + QString::number(spectralMatrixAddress2, 16)); + emit sendMessage(message); +} + +void SpectralMatricesDMASimulator::startSendingMatricesSLOT() +{ + nbMatricesSent = 0; + readMatrixAddress1SLOT(); + readMatrixAddress2SLOT(); + timer->start(40); +} + +void SpectralMatricesDMASimulator::stopSendingMatricesSLOT() +{ + timer->stop(); +} diff --git a/rmapplugin/spectralmatricesdmasimulator.h b/rmapplugin/spectralmatricesdmasimulator.h new file mode 100755 --- /dev/null +++ b/rmapplugin/spectralmatricesdmasimulator.h @@ -0,0 +1,60 @@ +#ifndef SPECTRALMATRICESDMASIMULATOR_H +#define SPECTRALMATRICESDMASIMULATOR_H + +#define APB_SPECTRAL_MATRICES_CTRL 0x80000700 +#define APB_SPECTRAL_MATRICES_DMA1 0x80000704 +#define APB_SPECTRAL_MATRICES_DMA2 0x80000708 +#define APB_ADDRESS_IRQCTRL 0x80000208 + +#include +#include +#include +#include + +#define SPECTRAL_MATRIX_SIZE 3840 + +class SpectralMatricesDMASimulator : public QWidget +{ + Q_OBJECT +public: + explicit SpectralMatricesDMASimulator(QWidget *parent = 0); + QVBoxLayout *mainLayout; + +signals: + void rmapplugginRead(unsigned int *Value, unsigned int count, unsigned int address); + void rmapplugginWrite(unsigned int *Value, unsigned int count, unsigned int address); + void sendMessage(QString message); + +public slots: + void sendOneSpectralMatrixSLOT(); + void sendOneSpectralMatrix1SLOT(); + void sendOneSpectralMatrix2SLOT(); + void startSendingMatricesSLOT(); + void stopSendingMatricesSLOT(); + void readMatrixAddress1SLOT(); + void readMatrixAddress2SLOT(); + +private: + unsigned int *Value; + unsigned int count; + unsigned int address; + unsigned int spectralMatrixCTRL; + unsigned int spectralMatrixAddress1; + unsigned int spectralMatrixAddress2; + unsigned int irqctrlForce; + unsigned int nbMatricesSent; + + QPushButton *sendOneSpectralMatrix1Button; + QPushButton *sendOneSpectralMatrix2Button; + QPushButton *sendSpectralMatricesPeriodicallyButton; + QPushButton *readMatrixAddress1Button; + QPushButton *readMatrixAddress2Button; + QPushButton *startSendingMatricesButton; + QPushButton *stopSendingMatricesButton; + + bool flagSendMatrix1; + + QTimer *timer; +}; + +#endif // SPECTRALMATRICESDMASIMULATOR_H diff --git a/rmapplugin/spwpacketreceiver.cpp b/rmapplugin/spwpacketreceiver.cpp new file mode 100755 --- /dev/null +++ b/rmapplugin/spwpacketreceiver.cpp @@ -0,0 +1,129 @@ +#include "spwpacketreceiver.h" +#include + +spwpacketreceiver::spwpacketreceiver(QObject *parent) : + QObject(parent) +{ + rmapPacketSEMAPHORE = new QSemaphore; + ccsdsPacketSEMAPHORE = new QSemaphore; + rmapPacket = (char*) malloc(RMAP_MAX_PACKET_LENGTH); + ccsdsPacket = (unsigned char*) malloc(CCSDS_MAX_PACKET_LENGTH); + spwPacket = (char*) malloc( qMax(RMAP_MAX_PACKET_LENGTH, CCSDS_MAX_PACKET_LENGTH) ); + connect(this, SIGNAL(ccsdsPacketAvailable(unsigned char*,uint)), this, SLOT(processCCSDSPacket(unsigned char*,uint))); +} + +spwpacketreceiver::~spwpacketreceiver() +{ + free(rmapPacket); + free(ccsdsPacket); + free(spwPacket); +} + +int spwpacketreceiver::receiveSPWPacket(unsigned char requestID) // SLOT +{ + QTime spwPacketReceiverTimeout; + // GRESB HEADER + char RES_TR_EP; // 6 bits REserved + 1 bit TRuncated + 1 bit EP error end of packet + unsigned char packetLength2; + unsigned char packetLength1; + unsigned char packetLength0; + unsigned int packetLength; + + if (requestID==1) + { + if (rmapPacketSEMAPHORE->available()) return rmapPacketSize; + } + + gresbReceptionSocket->blockSignals(1); // block the signals of the socket during packet reception + // READ THE GRESB HEADER OF THE INCOMING PACKET + spwPacketReceiverTimeout.start(); + while(gresbReceptionSocket->bytesAvailable() < 4) + { + gresbReceptionSocket->waitForReadyRead(100); + if(spwPacketReceiverTimeout.elapsed()>1000) return -1; // ERROR === read GRSEB header TIMEOUT + } + gresbReceptionSocket->read(&RES_TR_EP, 1); + gresbReceptionSocket->read( (char*) &packetLength2, 1); + gresbReceptionSocket->read( (char*) &packetLength1, 1); + gresbReceptionSocket->read( (char*) &packetLength0, 1); + packetLength = (packetLength2<<16) + (packetLength1<<8) + (packetLength0); + spwPacket = (char*) malloc(packetLength); + + // READ THE SPW PACKET + while(gresbReceptionSocket->bytesAvailable() < packetLength) + { + gresbReceptionSocket->waitForReadyRead(100); + if(spwPacketReceiverTimeout.elapsed()>1000) return -2; // ERROR === read SPW packet TIMEOUT + } + gresbReceptionSocket->read( spwPacket, packetLength ); + gresbReceptionSocket->blockSignals(0); + + switch(spwPacket[1]) // byte 1 is the protocole identifier in the SPW packet + { + case 1: // 0x01 is the protocole identifier for RMAP packets + if (rmapPacketSEMAPHORE->available()!=0) return -3; // ERROR === previous RMAP packet not processed yet + for(unsigned int i=0; irelease(); + //emit sendMessage("RMAP packet of size " + QString::number(packetLength) + " received"); + return packetLength; + + case 2: // 0x02 is the protocole identifier for CCSDS packets + if (ccsdsPacketSEMAPHORE->available()!=0) return -4; // ERROR === previous CCSDS packet not processed yet + for(unsigned int i=0; irelease(); + emit(ccsdsPacketAvailable(ccsdsPacket, packetLength)); + return packetLength; + } + return 0; +} + +bool spwpacketreceiver::isRMAPPacketSemaphoreAvailable() +{ + if (rmapPacketSEMAPHORE->available()!=0) return true; + return false; +} + +void spwpacketreceiver::acquireRMAPSemaphore() +{ + rmapPacketSEMAPHORE->acquire(); +} + +void spwpacketreceiver::acquireCCSDSSemaphore() +{ + ccsdsPacketSEMAPHORE->acquire(); +} + +void spwpacketreceiver::processCCSDSPacket(unsigned char *ccsdsPacket, unsigned int size) +{ + QString message; + unsigned int fine_time_value = 0; + fine_time_value = ((unsigned int) ccsdsPacket[7]<<24) + + ((unsigned int) ccsdsPacket[6]<<16) + + ((unsigned int) ccsdsPacket[5]<<8) + + ((unsigned int) ccsdsPacket[4]); + message.append(QTime::currentTime().toString() +":" + QString::number(QTime::currentTime().msec()) + ": "); + message.append("size " + + QString::number(size) + +" *** header " + + QString::number(ccsdsPacket[0], 16) + + " " + + QString::number(ccsdsPacket[1], 16) + + " " + + QString::number(ccsdsPacket[2], 16) + + " " + + QString::number(ccsdsPacket[3], 16) + + " *** coarse time " + + QString::number(fine_time_value)); + //+ QString::number(ccsdsPacket[4], 16) + //+" " + //+ QString::number(ccsdsPacket[5], 16) + //+" " + //+ QString::number(ccsdsPacket[6], 16) + //+" " + //+ QString::number(ccsdsPacket[7], 16)); + ccsdsPacketSEMAPHORE->acquire(); + emit sendMessage(message); +} + diff --git a/rmapplugin/spwpacketreceiver.h b/rmapplugin/spwpacketreceiver.h new file mode 100755 --- /dev/null +++ b/rmapplugin/spwpacketreceiver.h @@ -0,0 +1,44 @@ +#ifndef SPWPACKETRECEIVER_H +#define SPWPACKETRECEIVER_H + +#include +#include + +#define READ_WRITE_MAX_COUNTS 4096 // in words +#define RMAP_MAX_DATA_LENGTH 4*READ_WRITE_MAX_COUNTS // in bytes, shall be lower than the limit size of SPW packet of the GRESB bridge +#define RMAP_READ_REPLY_HEADER_LENGTH 12 // in bytes => ECSS +#define RMAP_READ_COMMAND_HEADER_LENGTH 16 // in bytes => ECSS +#define RMAP_DATA_CRC_LENGTH 1 // in bytes => ECSS +#define RMAP_MAX_PACKET_LENGTH RMAP_READ_REPLY_HEADER_LENGTH + RMAP_MAX_DATA_LENGTH + RMAP_DATA_CRC_LENGTH +#define CCSDS_MAX_PACKET_LENGTH 4412 // in bytes, specified in the LFR Software Requirements Specification + +class spwpacketreceiver : public QObject +{ + Q_OBJECT +public: + explicit spwpacketreceiver(QObject *parent = 0); + ~spwpacketreceiver(); + int fetchRMAPPacket(); + void acquireRMAPSemaphore(); + void acquireCCSDSSemaphore(); + bool isRMAPPacketSemaphoreAvailable(); + + unsigned char* ccsdsPacket; + char* rmapPacket; + char* spwPacket; + unsigned int rmapPacketSize; + unsigned int ccsdsPacketSize; + QSemaphore* rmapPacketSEMAPHORE; + QSemaphore* ccsdsPacketSEMAPHORE; + QTcpSocket* gresbReceptionSocket; + +public slots: + int receiveSPWPacket(unsigned char requestID = 0); // request ID by default is 0 for CCSDS + void processCCSDSPacket(unsigned char *ccsdsPacket, unsigned int size); + +signals: + void ccsdsPacketAvailable(unsigned char* ccsdsPacket, unsigned int size); + void sendMessage(QString message); +}; + +#endif // SPWPACKETRECEIVER_H diff --git a/rmapplugin/stardundee.cpp b/rmapplugin/stardundee.cpp new file mode 100644 --- /dev/null +++ b/rmapplugin/stardundee.cpp @@ -0,0 +1,55 @@ +#include "stardundee.h" + +StarDundee::StarDundee(QWidget *parent) : + QWidget(parent) +{ + connection_LAYOUT = new QGridLayout; + + openCommunication_BUTTON = new QPushButton(tr("Open communication link")); + closeCommunication_BUTTON = new QPushButton(tr("Close communication link")); + + usbDeviceNumber_LABEL = new QLabel(tr("USB device number: ")); + + usbDeviceNumber_SPINBOX = new QSpinBox; + usbDeviceNumber_SPINBOX->setRange(0,32); + usbDeviceNumber_SPINBOX->setValue(0); + + closeCommunication_BUTTON->setEnabled(false); + + connection_LAYOUT->addWidget(openCommunication_BUTTON, 0, 0, 1, 2); + connection_LAYOUT->addWidget(closeCommunication_BUTTON, 1, 0, 1, 2); + connection_LAYOUT->addWidget(usbDeviceNumber_LABEL, 2, 0, 1, 1); + connection_LAYOUT->addWidget(usbDeviceNumber_SPINBOX, 2, 1, 1, 1); + + this->setLayout(connection_LAYOUT); + + connect(this->openCommunication_BUTTON, SIGNAL(clicked()), this, SLOT(OpenStarDundee())); + connect(this->closeCommunication_BUTTON, SIGNAL(clicked()), this, SLOT(CloseStarDundee())); +} + +StarDundee::~StarDundee() +{ + USBSpaceWire_Close(hDevice); // Close the device +} + +unsigned int StarDundee::OpenStarDundee() +{ + if (!USBSpaceWire_Open(&hDevice, 0)) // Open the first device + { + emit sendMessage("stardundee *** Open *** ERROR: USBSpaceWire_Open(&hDevice, 0))"); + return -1; + } + openCommunication_BUTTON->setEnabled(false); + closeCommunication_BUTTON->setEnabled(true); + emit sendMessage("stardundee *** Open *** USBSpaceWire_Open(&hDevice, 0)) successful"); + return 1; +} + +unsigned int StarDundee::CloseStarDundee() +{ + USBSpaceWire_Close(hDevice); // Close the device + emit sendMessage("stardundee *** Close *** USBSpaceWire_Close(hDevice)"); + openCommunication_BUTTON->setEnabled(true); + closeCommunication_BUTTON->setEnabled(false); + return 1; +} diff --git a/rmapplugin/stardundee.h b/rmapplugin/stardundee.h new file mode 100644 --- /dev/null +++ b/rmapplugin/stardundee.h @@ -0,0 +1,38 @@ +#ifndef STARDUNDEE_H +#define STARDUNDEE_H + +#include +#include "spw_usb_api.h" +#include +#include +#include +#include + +class StarDundee : public QWidget +{ + Q_OBJECT +public: + explicit StarDundee(QWidget *parent = 0); + ~StarDundee(); + star_device_handle hDevice;// Handle to the SpaceWire device + QGridLayout *connection_LAYOUT; + +signals: + void sendMessage(QString message); + +public slots: + unsigned int OpenStarDundee(); + unsigned int CloseStarDundee(); + +private: + + QPushButton *openCommunication_BUTTON; + QPushButton *closeCommunication_BUTTON; + + QLabel *usbDeviceNumber_LABEL; + + QSpinBox *usbDeviceNumber_SPINBOX; + +}; + +#endif // STARDUNDEE_H diff --git a/spw_usb_driver_v2.61/inc/rmap_packet_library.h b/spw_usb_driver_v2.61/inc/rmap_packet_library.h new file mode 100644 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/rmap_packet_library.h @@ -0,0 +1,690 @@ +/** + * \file rmap_packet_library.h + * \brief Declarations of the functions provided by the STAR-Dundee RMAP Packet + * Library. + * STAR-Dundee\n + * Unit 12, Dundee University Incubator\n + * James Lindsay Place\n + * Dundee Technopole\n + * Dundee, DD1 5JJ\n + * Scotland, UK\n + * e-mail: support@star-dundee.com + * + * This file contains the declarations of the functions provided by the + * STAR-Dundee RMAP Packet Library, along with constants and types used by the + * library. The RMAP Packet Library provides functions for building and + * interpreting RMAP packets. + * + * IMPORTANT NOTE: + * \note If you are experiencing compilation errors indicating that + * U8 is already defined, for example, please add the following + * line to your code prior to including this file:\n + * \#define NO_STAR_TYPES\n + * Alternatively you can compile your code with a flag of + * -DNO_STAR_TYPES.\n + * (Copied from star_dundee_types.h) + * + * \version 3.2 - June 19th 2012\n + * Fixed bug when checking a write command packet or read reply packet + * has a data length of 0. + * Updates to documentation. + * + * \version 3.1 - February 10th 2012\n + * Minor updates to packet types to avoid errors in static + * analysers.\n\n + * + * \version 3.0 - October 14th 2011\n + * Updated linking process on Windows.\n + * Updated library file name.\n\n + * + * \version 2.1 - August 22nd 2011\n + * Made minor improvements to the internal structure.\n\n + * + * \version 2.0 - October 28th 2009\n + * Changed internal architecture to minimise memory allocations.\n + * Restored __stdcall calling convention on Windows.\n + * Updated names to be consistent with terminology in latest RMAP + * standard.\n + * Added functions to calculate the length of different packet types + * and to fill a buffer with specific packets.\n\n + * + * \version 1.9 - July 29th 2009\n + * Fixed problem with byte ordering in return value of + * RMAP_GetAddress.\n + * Fixed bug when creating read and write reply packets, with a packet + * structure provided.\n\n + * + * \version 1.8 - February 26th 2009\n + * Updated the calling convention used in the function declaration to + * __stdcall on Windows.\n\n + * + * \version 1.7 - November 20th 2008\n + * Fixed problem with naming of RMAP_IsCRCValid in header file.\n + * Added function to calculate a CRC starting from a CRC seed + * value.\n\n + * + * \version 1.6 - October 29th 2007\n + * Added support for SpaceCube.\n\n + * + * \version 1.5 - March 23rd 2007\n + * Used star_dundee_types.h to represent integer values of 1, 2 and 4 + * bytes in a cross-platform manner.\n + * Fixed problems encountered on big endian machines.\n\n + * + * \version 1.4 - March 19th 2007\n + * Improved freeing of memory following errors.\n\n + * + * \version 1.3 - November 7th 2006\n + * Updated to be multi-platform.\n + * Using new CRC table.\n + * Fixed error when checking the format of read-modify-write command + * packets, data length incorrect.\n + * Fixed error when identifying the start of the extended and normal + * read/write address.\n + * Fixed error when reading the data length in a read command.\n\n + * + * \version 1.2 - April 3rd 2006\n + * Fixed potential problems with RMAP_PACKET_STATUS enum being an + * undefined size (no change to this file required).\n\n + * + * \version 1.1 - March 9th 2006\n + * Added support for different byte alignment requirements.\n\n + * + * \version 1.0 - December 20th 2005\n + * Initial version.\n\n + * + * Copyright © 2009 STAR-Dundee Ltd + */ + + + +#ifndef RMAP_PACKET_LIBRARY_H +#define RMAP_PACKET_LIBRARY_H + + + +#include "star-dundee_types.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#if defined(_WIN32) || defined(_WIN64) + #ifdef _WIN64 + #define RMAPPACKETLIBRARY_CC + #else + #define RMAPPACKETLIBRARY_CC __stdcall + #endif +#else + #define RMAPPACKETLIBRARY_CC +#endif + + + +typedef enum +{ + RMAP_SUCCESS = 0x00, + RMAP_GENERAL_ERROR = 0x01, + RMAP_UNUSED_PACKET_TYPE_OR_COMMAND_CODE = 0x02, + RMAP_INVALID_KEY = 0x03, + RMAP_INVALID_DATA_CRC = 0x04, + RMAP_EARLY_EOP = 0x05, + RMAP_TOO_MUCH_DATA = 0x06, + RMAP_EEP = 0x07, + RMAP_VERIFY_BUFFER_OVERRUN = 0x09, + RMAP_COMMAND_NOT_IMPLEMENTED_OR_AUTHORISED = 0x0a, + RMAP_RMW_DATA_LENGTH_ERROR = 0x0b, + RMAP_INVALID_TARGET_LOGICAL_ADDRESS = 0x0c, + RMAP_INVALID_STATUS = 0xff +} RMAP_STATUS; + + + +#define RMAP_PROTOCOL_IDENTIFIER 1 + +#define RMAP_RESERVED_BIT 0x80 +#define RMAP_COMMAND_BIT 0x40 +#define RMAP_WRITE_OPERATION_BIT 0x20 +#define RMAP_VERIFY_BEFORE_WRITE_BIT 0x10 +#define RMAP_REPLY_BIT 0x08 +#define RMAP_INCREMENT_ADDRESS_BIT 0x04 +#define RMAP_REPLY_ADDRESS_LENGTH_BITS 0x03 + + + +typedef enum +{ + RMAP_WRITE_COMMAND = (RMAP_COMMAND_BIT | + RMAP_WRITE_OPERATION_BIT), + RMAP_WRITE_REPLY = (RMAP_WRITE_OPERATION_BIT), + RMAP_READ_COMMAND = (RMAP_COMMAND_BIT), + RMAP_READ_REPLY = (0), + RMAP_READ_MODIFY_WRITE_COMMAND = (RMAP_COMMAND_BIT | + RMAP_VERIFY_BEFORE_WRITE_BIT), + RMAP_READ_MODIFY_WRITE_REPLY = (RMAP_VERIFY_BEFORE_WRITE_BIT), + RMAP_INVALID_PACKET_TYPE = (0xff) +} RMAP_PACKET_TYPE; + + + +typedef struct +{ + RMAP_PACKET_TYPE packetType; + U8 *pTargetAddress; + unsigned long targetAddressLength; + U8 *pReplyAddress; + unsigned long replyAddressLength; + U8 *pProtocolIdentifier; + U8 *pInstruction; + char verifyBeforeWrite; + char acknowledge; + char incrementAddress; + U8 *pKey; + U16 *pTransactionIdentifier; + U32 *pReadWriteAddress; + U8 *pExtendedReadWriteAddress; + U8 *pStatus; + U8 *pHeader; + unsigned long headerLength; + U8 *pHeaderCRC; + U8 *pData; + void *pDataLength; + U32 dataLength; + U8 *pDataCRC; + U8 *pMask; + U8 maskLength; + U8 *pRawPacket; + unsigned long rawPacketLength; +} RMAP_PACKET; + + + +/* Declarations of the functions provided by the RMAP Packet Library */ + +U32 +RMAPPACKETLIBRARY_CC +RMAP_GetVersion( + void + ); + +U8 +RMAPPACKETLIBRARY_CC +RMAP_CalculateCRC( + void *pBuffer, + unsigned long len + ); + +U8 +RMAPPACKETLIBRARY_CC +RMAP_CalculateCRCWithSeed( + void *pBuffer, + unsigned long len, + U8 crc + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_IsCRCValid( + void *pBuffer, + unsigned long len, + U8 crc + ); + +RMAP_STATUS +RMAPPACKETLIBRARY_CC +RMAP_CheckPacketValid( + void *pRawPacket, + unsigned long packetLength, + RMAP_PACKET *pPacketStruct, + char checkPacketTooLong + ); + +RMAP_PACKET_TYPE +RMAPPACKETLIBRARY_CC +RMAP_GetPacketType( + RMAP_PACKET *pPacketStruct + ); + +U8 * +RMAPPACKETLIBRARY_CC +RMAP_GetTargetAddress( + RMAP_PACKET *pPacketStruct, + unsigned long *pTargetAddressLength + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_GetVerifyBeforeWrite( + RMAP_PACKET *pPacketStruct + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_GetPerformAcknowledgement( + RMAP_PACKET *pPacketStruct + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_GetIncrementAddress( + RMAP_PACKET *pPacketStruct + ); + +U8 +RMAPPACKETLIBRARY_CC +RMAP_GetKey( + RMAP_PACKET *pPacketStruct + ); + +U8 * +RMAPPACKETLIBRARY_CC +RMAP_GetReplyAddress( + RMAP_PACKET *pPacketStruct, + unsigned long *pReplyAddressLength + ); + +U16 +RMAPPACKETLIBRARY_CC +RMAP_GetTransactionID( + RMAP_PACKET *pPacketStruct + ); + +U32 +RMAPPACKETLIBRARY_CC +RMAP_GetAddress( + RMAP_PACKET *pPacketStruct, + U8 *pExtendedAddress + ); + +U8 * +RMAPPACKETLIBRARY_CC +RMAP_GetData( + RMAP_PACKET *pPacketStruct, + U32 *pDataLength + ); + +U32 +RMAPPACKETLIBRARY_CC +RMAP_GetReadLength( + RMAP_PACKET* pPacketStruct + ); + +RMAP_STATUS +RMAPPACKETLIBRARY_CC +RMAP_GetStatus( + RMAP_PACKET *pPacketStruct + ); + +U8 +RMAPPACKETLIBRARY_CC +RMAP_GetHeaderCRC( + RMAP_PACKET *pPacketStruct + ); + +U8 +RMAPPACKETLIBRARY_CC +RMAP_GetDataCRC( + RMAP_PACKET *pPacketStruct + ); + +U8 * +RMAPPACKETLIBRARY_CC +RMAP_GetMask( + RMAP_PACKET *pPacketStruct, + U8 *pMaskLength + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateWriteCommandPacketLength( + unsigned long targetAddressLength, + unsigned long replyAddressLength, + U32 dataLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillWriteCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char verifyBeforeWrite, + char acknowledge, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 writeAddress, + U8 extendedWriteAddress, + U8 *pData, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildWriteCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char verifyBeforeWrite, + char acknowledge, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 writeAddress, + U8 extendedWriteAddress, + U8 *pData, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildWriteRegisterPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char verifyBeforeWrite, + char acknowledge, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 writeAddress, + U8 extendedWriteAddress, + U32 registerValue, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateWriteReplyPacketLength( + unsigned long initiatorAddressLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillWriteReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + char verifyBeforeWrite, + char incrementAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildWriteReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + char verifyBeforeWrite, + char incrementAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateReadCommandPacketLength( + unsigned long targetAddressLength, + unsigned long replyAddressLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillReadCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 readAddress, + U8 extendedReadAddress, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 readAddress, + U8 extendedReadAddress, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadRegisterPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + char incrementAddress, + U8 key, + U16 transactionIdentifier, + U32 readAddress, + U8 extendedReadAddress, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateReadReplyPacketLength( + unsigned long initiatorAddressLength, + U32 dataLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillReadReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + char incrementAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + U8 *pData, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + char incrementAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + U8 *pData, + U32 dataLength, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateReadModifyWriteCommandPacketLength( + unsigned long targetAddressLength, + unsigned long replyAddressLength, + U32 dataAndMaskLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillReadModifyWriteCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + U8 key, + U16 transactionIdentifier, + U32 readModifyWriteAddress, + U8 extendedReadModifyWriteAddress, + U8 dataAndMaskLength, + U8 *pData, + U8 *pMask, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadModifyWriteCommandPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + U8 key, + U16 transactionIdentifier, + U32 readModifyWriteAddress, + U8 extendedReadModifyWriteAddress, + U8 dataAndMaskLength, + U8 *pData, + U8 *mask, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadModifyWriteRegisterPacket( + U8 *pTargetAddress, + unsigned long targetAddressLength, + U8 *pReplyAddress, + unsigned long replyAddressLength, + U8 key, + U16 transactionIdentifier, + U32 readModifyWriteAddress, + U8 extendedReadModifyWriteAddress, + U32 registerValue, + U32 mask, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +unsigned long +RMAPPACKETLIBRARY_CC +RMAP_CalculateReadModifyWriteReplyPacketLength( + unsigned long initiatorAddressLength, + U32 dataLength, + char alignment + ); + +char +RMAPPACKETLIBRARY_CC +RMAP_FillReadModifyWriteReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + unsigned long dataLength, + U8 *pData, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment, + U8 *pRawPacket, + unsigned long rawPacketLength + ); + +void * +RMAPPACKETLIBRARY_CC +RMAP_BuildReadModifyWriteReplyPacket( + U8 *pInitiatorAddress, + unsigned long initiatorAddressLength, + U8 targetAddress, + RMAP_STATUS status, + U16 transactionIdentifier, + unsigned long dataLength, + U8 *pData, + unsigned long *pRawPacketLength, + RMAP_PACKET *pPacketStruct, + char alignment + ); + +void +RMAPPACKETLIBRARY_CC +RMAP_FreeBuffer( + void *pBuffer + ); + + +/* Macros for accessing the version */ + +#define RMAP_GET_VERSION_MAJOR(versionInfo) (((version) & 0xff000000) >> 24) +#define RMAP_GET_VERSION_MINOR(versionInfo) (((version) & 0x00ff0000) >> 16) +#define RMAP_GET_VERSION_EDIT(versionInfo) (((version) & 0x0000ffc0) >> 6) +#define RMAP_GET_VERSION_PATCH(versionInfo) ((version) & 0x0000003f) + + + +#ifdef __cplusplus +} +#endif + + + +#endif /* RMAP_PACKET_LIBRARY_H */ + + + diff --git a/spw_usb_driver_v2.61/inc/spacewire_usb.h b/spw_usb_driver_v2.61/inc/spacewire_usb.h new file mode 100755 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/spacewire_usb.h @@ -0,0 +1,205 @@ +/******************************************************************************/ +/* */ +/* spacewire_usb.h */ +/* */ +/* Header file for all constants which may be used with the STAR-Dundee */ +/* SpaceWire USB driver. */ +/* */ +/* Version 2.61, September 17th 2012 */ +/* */ +/* Version 2.61, 17/09/12 */ +/* ====================== */ +/* Added support for STAR Fire and WBS II. */ +/* */ +/* Version 2.60, 04/01/12 */ +/* ====================== */ +/* Added support for EGSE and SPLT. */ +/* */ +/* Version 2.59, 15/08/11 */ +/* ====================== */ +/* Added support for RTC. */ +/* */ +/* Version 2.58, 12/10/10 */ +/* ===================== */ +/* Added support for Link Analyser Mk2. */ +/* */ +/* Version 2.51 */ +/* ============ */ +/* Added use of star_dundee_types.h. */ +/* */ +/* Version 2.5 */ +/* =========== */ +/* Initial version, following change to new architecture. */ +/* */ +/* Copyright (2012), STAR-Dundee Ltd., */ +/* STAR House, */ +/* 166 Nethergate, */ +/* Dundee, DD1 4EE, */ +/* Scotland, UK. */ +/* e-mail: support@star-dundee.com */ +/* */ +/******************************************************************************/ + + + +#ifndef SPACEWIRE_USB_H +#define SPACEWIRE_USB_H + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* The types used by the API */ +#include "star_dundee_types.h" + + +/* End of packet marker types */ +#define SPACEWIRE_USB_EOP_CHAR ((U8)0x80) +#define SPACEWIRE_USB_EEP_CHAR ((U8)0x40) + +/* The protocol byte used to identify LODI packets */ +#define SPACEWIRE_USB_LODI_PROTOCOL (0xd1) + + + +/* Possible results of read and send operations */ +typedef enum +{ + TRANSFER_NOT_STARTED = 0, + TRANSFER_STARTED = 1, + TRANSFER_SUCCESS = 2, + TRANSFER_ERROR_DISCONNECT = 3, + TRANSFER_ERROR_PARITY = 4, + TRANSFER_ERROR_UNKNOWN = 5, + TRANSFER_ERROR_TIMEOUT = 6, + TRANSFER_ERROR_LINK_NOT_STARTED = 7, + TRANSFER_ERROR_USER_BUFFER_LOCK_FAILED = 8, + TRANSFER_ERROR_LINK_ALREADY_IN_USE = 9, + TRANSFER_ERROR_RECEIVE_BUFFER_FULL = 0xa, + TRANSFER_ERROR_OUT_OF_MEMORY = 0xb, + TRANSFER_ERROR_NOT_FOUND = 0xc, + TRANSFER_ERROR_USB_ERROR = 0xd, + TRANSFER_ERROR_NOT_REGISTERED_TO_RECEIVE = 0xe +} USB_SPACEWIRE_STATUS, *PUSB_SPACEWIRE_STATUS; + + + +/* Possible traffic types */ +typedef enum +{ + SPACEWIRE_TRAFFIC_UNKNOWN = -1, + SPACEWIRE_TRAFFIC_PACKET = 0, + SPACEWIRE_TRAFFIC_TIMECODE = 1, + SPACEWIRE_TRAFFIC_CONTROL = 2 +} SPACEWIRE_TRAFFIC_TYPE, *PSPACEWIRE_TRAFFIC_TYPE; + + + +/* The different end of packet marker types */ +typedef enum +{ + SPACEWIRE_USB_NO_EOP = 0, + SPACEWIRE_USB_EOP = SPACEWIRE_USB_EOP_CHAR, + SPACEWIRE_USB_EEP = SPACEWIRE_USB_EEP_CHAR +} USB_SPACEWIRE_EOP_TYPE, *PUSB_SPACEWIRE_EOP_TYPE; + + + +/* Possible device types */ +typedef enum +{ + SPACEWIRE_DEVICE_UNKNOWN = -1, + SPACEWIRE_ROUTER_USB = 0, + SPACEWIRE_BRICK = 1, + SPACEWIRE_LINK_ANALYSER = 2, + SPACEWIRE_CONFORMANCE_TESTER = 3, + SPACEWIRE_TUNNEL_BRICK = 4, + SPACEWIRE_LINK_ANALYSER_MK2 = 5, + SPACEWIRE_RTC = 6, + SPACEWIRE_EGSE = 7, + SPACEWIRE_PHYSICAL_LAYER_TESTER = 8, + STAR_FIRE = 9, + WBS_II = 10 +} SPACEWIRE_DEVICE_TYPE, *PSPACEWIRE_DEVICE_TYPE; + + + + +/* Structure used to store packet lengths and EOPs for a read request */ +typedef struct +{ + unsigned long len; + USB_SPACEWIRE_EOP_TYPE eop; + SPACEWIRE_TRAFFIC_TYPE type; +} USB_SPACEWIRE_PACKET_PROPERTIES, *PUSB_SPACEWIRE_PACKET_PROPERTIES; + + + +/* The type of all send and receive identifiers */ +typedef void * USB_SPACEWIRE_ID; + + + +/* Structure used to represent the firmware version of a device */ +typedef struct +{ + U8 major; + U8 minor; + U16 edit; + U8 patch; +} SPACEWIRE_FIRMWARE_VERSION; + + +/* The product ID used by each STAR-Dundee SpaceWire device */ + +/** The product ID used by a device with no EEPROM */ +#define SPACEWIRE_PRODUCT_ID_NO_EEPROM (0x8613) +/** The product ID used by an old device in the power check state */ +#define SPACEWIRE_PRODUCT_ID_POWER_CHECK (0x461f) +/** The product ID used by an old device with no ID set */ +#define SPACEWIRE_PRODUCT_ID_NO_ID (0x1002) +/** The product ID used by the SpaceWire Router-USB */ +#define SPACEWIRE_PRODUCT_ID_ROUTER_USB (0x1011) +/** The product ID used by the SpaceWire-USB Brick */ +#define SPACEWIRE_PRODUCT_ID_BRICK (0x1012) +/** The product ID used by the SpaceWire Link Analyser */ +#define SPACEWIRE_PRODUCT_ID_LINK_ANALYSER (0x1013) +/** The product ID used by the SpaceWire Conformance Tester */ +#define SPACEWIRE_PRODUCT_ID_CONFORMANCE_TESTER (0x1014) +/** The product ID used by the SpaceWire-IP Tunnel */ +#define SPACEWIRE_PRODUCT_ID_TUNNEL_BRICK (0x1015) +/** The product ID used by the SpaceWire Router-USB with multiple channels */ +#define SPACEWIRE_PRODUCT_ID_ROUTER_MULTIPLE_CHANNELS (0x1016) +/** The product ID used by the SpaceWire Router-USB II Rev 4 */ +#define SPACEWIRE_PRODUCT_ID_ROUTER_USB_II_REV4 (0x1017) +/** The product ID used by the SpaceWire Link Analyser Mk2 */ +#define SPACEWIRE_PRODUCT_ID_LINK_ANALYSER_MK2 (0x1018) +/** The product ID used by the SpaceWire RTC */ +#define SPACEWIRE_PRODUCT_ID_RTC (0x1019) +/** The product ID used by the SpaceWire EGSE */ +#define SPACEWIRE_PRODUCT_ID_EGSE (0x101a) +/** The product ID used by the SpaceWire SPLT */ +#define SPACEWIRE_PRODUCT_ID_SPLT (0x101b) +/** The product ID used by the STAR Fire device */ +#define SPACEWIRE_PRODUCT_ID_STAR_FIRE (0x101c) +/** The product ID used by the WBS II device */ +#define SPACEWIRE_PRODUCT_ID_WBS_II (0x101d) +/** A product ID to be used by a future device */ +#define SPACEWIRE_PRODUCT_ID_FUTURE_101E (0x101e) +/** A product ID to be used by a future device */ +#define SPACEWIRE_PRODUCT_ID_FUTURE_101F (0x101f) + + +#ifdef __cplusplus +} +#endif + + + +#endif /* SPACEWIRE_USB_H */ + + + diff --git a/spw_usb_driver_v2.61/inc/spw_config_library.h b/spw_usb_driver_v2.61/inc/spw_config_library.h new file mode 100755 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/spw_config_library.h @@ -0,0 +1,656 @@ +/******************************************************************************/ +/* */ +/* spw_config_library.h */ +/* */ +/* Declaration of the functions, and definition of macros provided by the */ +/* SpaceWire Router Configuration Library for the SpaceWire USB and */ +/* SpaceWire PCI drivers. */ +/* */ +/* Version 2.60 - January 5th 2012 */ +/* */ +/* Version 2.60 - 05/04/12 */ +/* ======================= */ +/* Updated declarations to replace CFGSpaceWire_EnableReadOnAllPorts */ +/* with CFGSpaceWire_EnableReceiveOnAllPorts and */ +/* CFGSpaceWire_IsReadingOnAllPortsEnabled with */ +/* CFGSpaceWire_IsReceiveOnAllPortsEnabled. */ +/* */ +/* Version 2.54 - 10/12/10 */ +/* ======================= */ +/* Replaced CFGSpaceWire_RTOutputPorts with */ +/* CFGSpaceWire_RTGetOutputPorts, which doesn't unnecessarily shift the */ +/* output port bits and is consistent with */ +/* CFGSpaceWire_RTBuildRoutingTableEntry. */ +/* */ +/* Version 2.53 - 26/02/09 */ +/* ======================= */ +/* Updated the calling convention used in the function declarations to */ +/* __stdcall on Windows. */ +/* */ +/* Version 2.52, 04/11/08 */ +/* ====================== */ +/* Added support for precision transmit rate on new Router-USB. */ +/* Added chip ID values. */ +/* */ +/* Version 2.51, 21/10/08 */ +/* ====================== */ +/* Updated to support Windows. */ +/* */ +/* Version 2.50, 08/11/06 */ +/* ====================== */ +/* Initial version, following change to new structure. */ +/* */ +/* Copyright (c) 2012, Stuart Mills, */ +/* STAR-Dundee, */ +/* c/o School of Computing, */ +/* University of Dundee, */ +/* Dundee, DD1 4HN, */ +/* Scotland, UK. */ +/* http://www.star-dundee.com */ +/* e-mail: support@star-dundee.com */ +/* */ +/******************************************************************************/ + + + +#ifndef SPACEWIRE_ROUTER_LIBRARY +#define SPACEWIRE_ROUTER_LIBRARY + + +#include "star_dundee_types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#if defined(_WIN32) || defined(_WIN64) + + +/* Windows specifc functions and macros */ + +#ifdef ROUTERCONFIGURATIONLIBRARY_EXPORTS +#define ROUTER_CONFIG_LIBRARY __declspec(dllexport) +#else +#define ROUTER_CONFIG_LIBRARY __declspec(dllimport) +#endif + +/* The calling convention to be used */ +#ifdef _WIN64 +#define ROUTER_CONFIG_CC +#else +#define ROUTER_CONFIG_CC __stdcall +#endif /* WIN64 */ + + +#include "windows.h" + + +#else /* _WIN32 */ + + +/* Linux specific functions and macros */ + +#define ROUTER_CONFIG_LIBRARY +#define ROUTER_CONFIG_CC + + +#endif /* _WIN32 */ + + + +/* Possible bit values */ +#define BIT0 (0x00000001) +#define BIT1 (0x00000002) +#define BIT2 (0x00000004) +#define BIT3 (0x00000008) +#define BIT4 (0x00000010) +#define BIT5 (0x00000020) +#define BIT6 (0x00000040) +#define BIT7 (0x00000080) +#define BIT8 (0x00000100) +#define BIT9 (0x00000200) +#define BIT10 (0x00000400) +#define BIT11 (0x00000800) +#define BIT12 (0x00001000) +#define BIT13 (0x00002000) +#define BIT14 (0x00004000) +#define BIT15 (0x00008000) +#define BIT16 (0x00010000) +#define BIT17 (0x00020000) +#define BIT18 (0x00040000) +#define BIT19 (0x00080000) +#define BIT20 (0x00100000) +#define BIT21 (0x00200000) +#define BIT22 (0x00400000) +#define BIT23 (0x00800000) +#define BIT24 (0x01000000) +#define BIT25 (0x02000000) +#define BIT26 (0x04000000) +#define BIT27 (0x08000000) +#define BIT28 (0x10000000) +#define BIT29 (0x20000000) +#define BIT30 (0x40000000) +#define BIT31 (0x80000000) + + + +/* Exported enums and structs */ + + + +/* Read write address errors */ +typedef enum +{ + CFG_TRANSFER_SUCCESS = 0x00, + CFG_TRANSMIT_PACKET_FAILURE = 0x01, + CFG_REPLY_PACKET_FAILURE = 0x02, + CFG_REPLY_PACKET_TOO_BIG = 0x03, + CFG_REPLY_PACKET_TOO_SMALL = 0x04, + CFG_REPLY_PACKET_NAK = 0x05, + CFG_REPLY_PACKET_CHECKSUM_ERROR = 0x06, +} CFG_SPACEWIRE_STATUS; + + + +/* Length of port timeout */ +typedef enum +{ + CFG_PORT_TIMEOUT_100US = 0x0, + CFG_PORT_TIMEOUT_1MS = 0x1, + CFG_PORT_TIMEOUT_10MS = 0x2, + CFG_PORT_TIMEOUT_100MS = 0x3, + CFG_PORT_TIMEOUT_1S = 0x4, +} CFG_SPACEWIRE_PORT_TIMEOUT; + + + +/* SpaceWire Port errors */ +#define CFG_SPACEWIRE_NO_ERRORS (0) +#define CFG_SPACEWIRE_ERROR_ACTIVE (BIT0) +#define CFG_SPACEWIRE_PACKET_ADDRESS_ERROR (BIT1) +#define CFG_SPACEWIRE_PORT_TIMEOUT_ERROR (BIT2) +#define CFG_SPACEWIRE_DISCONNECT_ERROR (BIT3) +#define CFG_SPACEWIRE_PARITY_ERROR (BIT4) +#define CFG_SPACEWIRE_ESCAPE_ERROR (BIT5) +#define CFG_SPACEWIRE_CREDIT_ERROR (BIT6) +#define CFG_SPACEWIRE_CHARACTER_SEQUENCE_ERROR (BIT7) +#define CFG_SPACEWIRE_ERROR_BITS (BIT0 | BIT1 | BIT2 | BIT3 | \ + BIT4 | BIT5 | BIT6 | BIT7) + +/* Config Port errors */ +#define CFG_CONFIG_NO_ERRORS (0) +#define CFG_CONFIG_ERROR_ACTIVE (BIT0) + +/* Config Port errors (non-RMAP) */ +#define CFG_CONFIG_PACKET_ADDRESS_ERROR (BIT1) +#define CFG_CONFIG_PORT_TIMEOUT_ERROR (BIT2) +#define CFG_CONFIG_CHECKSUM_ERROR (BIT3) +#define CFG_CONFIG_TOO_SHORT_ERROR (BIT4) +#define CFG_CONFIG_TOO_LONG_ERROR (BIT5) +#define CFG_CONFIG_PACKET_EEP_ERROR (BIT6) +#define CFG_CONFIG_PROTOCOL_BYTE_ERROR (BIT7) +#define CFG_CONFIG_INVALID_REGISTER_ERROR (BIT8) +#define CFG_CONFIG_ERROR_BITS (BIT0 | BIT1 | BIT2 | BIT3 | \ + BIT4 | BIT5 | BIT6 | BIT7 | \ + BIT8) + +/* Config Port errors (RMAP) */ +#define CFG_CONFIG_RMAP_PORT_TIMEOUT_ERROR (BIT1) +#define CFG_CONFIG_RMAP_INVALID_HEADER_CRC (BIT2) +#define CFG_CONFIG_RMAP_INVALID_DATA_CRC (BIT3) +#define CFG_CONFIG_RMAP_INVALID_DESTINATION_KEY (BIT4) +#define CFG_CONFIG_RMAP_COMMAND_NOT_IMPLEMENTED (BIT5) +#define CFG_CONFIG_RMAP_INVALID_DATA_LENGTH (BIT6) +#define CFG_CONFIG_RMAP_INVALID_RMW_DATA_LENGTH (BIT7) +#define CFG_CONFIG_RMAP_INVALID_DESTINATION_ADDRESS (BIT8) +#define CFG_CONFIG_RMAP_EARLY_EOP (BIT9) +#define CFG_CONFIG_RMAP_LATE_EOP (BIT10) +#define CFG_CONFIG_RMAP_EARLY_EEP (BIT11) +#define CFG_CONFIG_RMAP_LATE_EEP (BIT12) +#define CFG_CONFIG_RMAP_VERIFY_BUFFER_OVERRUN_ERROR (BIT13) +#define CFG_CONFIG_RMAP_INVALID_REGISTER_ADDRESS (BIT14) +#define CFG_CONFIG_RMAP_UNSUPPORTED_PROTOCOL_ERROR (BIT15) +#define CFG_CONFIG_RMAP_SOURCE_LOGICAL_ADDRESS_ERROR (BIT16) +#define CFG_CONFIG_RMAP_SOURCE_PATH_ADDRESS_ERROR (BIT17) +#define CFG_CONFIG_RMAP_CARGO_TOO_LARGE (BIT18) +#define CFG_CONFIG_RMAP_UNUSED_COMMAND_OR_PACKET_TYPE (BIT19) +#define CFG_CONFIG_RMAP_ERROR_BITS (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | \ + BIT5 | BIT6 | BIT7 | BIT8 | BIT9 | \ + BIT10 | BIT11 | BIT12 | BIT13 | \ + BIT14 | BIT15 | BIT16 | BIT17 | \ + BIT18 | BIT19) + +/* External Port errors */ +#define CFG_EXTERNAL_NO_ERRORS (0) +#define CFG_EXTERNAL_ERROR_ACTIVE (BIT0) +#define CFG_EXTERNAL_PACKET_ADDRESS_ERROR (BIT1) +#define CFG_EXTERNAL_PORT_TIMEOUT_ERROR (BIT2) +#define CFG_EXTERNAL_INPUT_BUFFER_EMPTY_ERROR (BIT3) +#define CFG_EXTERNAL_INPUT_BUFFER_FULL_ERROR (BIT4) +#define CFG_EXTERNAL_OUTPUT_BUFFER_EMPTY_ERROR (BIT5) +#define CFG_EXTERNAL_OUTPUT_BUFFER_FULL_ERROR (BIT6) +#define CFG_EXTERNAL_ERROR_BITS (BIT0 | BIT1 | BIT2 | BIT3 | \ + BIT4 | BIT5 | BIT6) + +/* SpaceWire Port interface state */ +#define CFG_SPACEWIRE_ERROR_RESET (0) +#define CFG_SPACEWIRE_ERROR_WAIT (BIT0) +#define CFG_SPACEWIRE_READY (BIT1) +#define CFG_SPACEWIRE_STARTED (BIT1 | BIT0) +#define CFG_SPACEWIRE_CONNECTING (BIT2) +#define CFG_SPACEWIRE_RUN (BIT2 | BIT0) + +/* Port type */ +#define CFG_CONFIGURATION_PORT (0) +#define CFG_SPACEWIRE_SERIAL_PORT (BIT0) +#define CFG_SPACEWIRE_EXTERNAL_PORT (BIT1) + +/* SpaceWire Port control bits */ +#define CFG_SPACEWIRE_INTERFACE_STATE_START (8) +#define CFG_SPACEWIRE_INTERFACE_STATE (BIT8 | BIT9 | BIT10) +#define CFG_SPACEWIRE_RUNNING (BIT11) +#define CFG_SPACEWIRE_AUTOSTART (BIT12) +#define CFG_SPACEWIRE_START (BIT13) +#define CFG_SPACEWIRE_DISABLE (BIT14) +#define CFG_SPACEWIRE_TRISTATE (BIT15) +#define CFG_SPACEWIRE_RATE (BIT16 | BIT17 | BIT18 | \ + BIT19 | BIT20 | BIT21 | BIT22) +#define CFG_SPACEWIRE_RATE_START (16) + +/* Bits in the GAR Table */ +#define CFG_GAR_OUTPUT_PORTS_START (1) +#define CFG_GAR_OUTPUT_PORTS (BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | \ + BIT6 | BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13 | BIT14 | \ + BIT15 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | \ + BIT23 | BIT24 | BIT25 | BIT26 | BIT27 | BIT28) +#define CFG_GAR_DEL_HEAD (BIT29) +#define CFG_GAR_PRIORITY (BIT30) +#define CFG_GAR_INVALID_ADDR (BIT31) + +/* Bits in the router control register */ +#define CFG_RC_TIMEOUT_ENABLE_START (0) +#define CFG_RC_TIMEOUT_ENABLE (BIT0) +#define CFG_RC_TIMEOUT_VALUE_START (1) +#define CFG_RC_TIMEOUT_VALUE (BIT1 | BIT2 | BIT3) +#define CFG_RC_DISABLE_ON_SILENCE (BIT4) +#define CFG_RC_DISABLE_ON_SILENCE_START (4) +#define CFG_RC_START_ON_REQUEST (BIT5) +#define CFG_RC_START_ON_REQUEST_START (5) +#define CFG_RC_SELF_ADDRESSING (BIT6) +#define CFG_RC_SELF_ADDRESSING_START (6) +#define CFG_RC_INTERFACE (BIT7) +#define CFG_RC_INTERFACE_START (7) +#define CFG_RC_INTERFACE_IDENT (BIT8) +#define CFG_RC_INTERFACE_IDENT_START (8) + +/* The bits shared by all ports */ +#define CFG_PORT_CONNECTION (BIT24 | BIT25 | BIT26 | BIT27 | BIT28) +#define CFG_PORT_CONNECTION_START (24) +#define CFG_PORT_TYPE (BIT29 | BIT30 | BIT31) +#define CFG_PORT_TYPE_START (29) + +/* Network discovery register values */ +#define CFG_NETD_TYPE (BIT0 | BIT1 | BIT2 | BIT3) +#define CFG_NETD_TYPE_START (0) +#define CFG_NETD_RETURN_PORT (BIT4 | BIT5 | BIT6 | BIT7) +#define CFG_NETD_RETURN_PORT_START (4) +#define CFG_NETD_RUNNING_PORTS (BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | \ + BIT13 | BIT14 | BIT15 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | \ + BIT21 | BIT22 | BIT23 | BIT24 | BIT25 | BIT26 | BIT27 | BIT28 | \ + BIT29 | BIT30 | BIT31) +#define CFG_NETD_RUNNING_PORTS_START (8) + +/* Values in the ID register */ +#define CFG_ID_VERSION (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | \ + BIT5 | BIT6 | BIT7) +#define CFG_ID_VERSION_START (0) +#define CFG_ID_CHIP (BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | \ + BIT13 | BIT14 | BIT15) +#define CFG_ID_CHIP_START (8) +#define CFG_ID_MANUFACTURER (BIT16 | BIT17 | BIT18 | BIT19 | \ + BIT20 | BIT21 | BIT22 | BIT23) +#define CFG_ID_MANUFACTURER_START (16) + +/* Values in the Time-Code register */ +#define CFG_TC_VALUE (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | \ + BIT5) +#define CFG_TC_VALUE_START (0) +#define CFG_TC_FLAGS (BIT6 | BIT7) +#define CFG_TC_FLAGS_START (6) + +/* Values for the Router Base Clock Select */ +#define CFG_RTR_CLK_100_MBITS (0) +#define CFG_RTR_CLK_200_MBITS (BIT0) + +/* Values for the Brick Base Clock */ +#define CFG_BRK_CLK_100_MHZ (0) +#define CFG_BRK_CLK_120_MHZ (BIT0) +#define CFG_BRK_CLK_140_MHZ (BIT1) +#define CFG_BRK_CLK_160_MHZ (BIT0 | BIT1) +#define CFG_BRK_CLK_180_MHZ (BIT2) +#define CFG_BRK_CLK_200_MHZ (BIT2 | BIT0) + +/* Values for the Brick Base Divider */ +#define CFG_BRK_DVDR_1 (0) +#define CFG_BRK_DVDR_2 (BIT0) +#define CFG_BRK_DVDR_4 (BIT1) + +/* Values in the Tx register */ +#define CFG_TX_BRICK_2MBITS (BIT27) +#define CFG_TX_BRICK_2MBITS_START (27) + +/* Values in the Precision Transmit Rate register */ +#define CFG_PT_ENABLE (BIT16) +#define CFG_PT_ENABLE_START (16) +#define CFG_PT_READY (BIT17) +#define CFG_PT_READY_START (17) +#define CFG_PT_IN_USE (BIT20) +#define CFG_PT_IN_USE_START (20) +#define CFG_PT_RATE_BITS (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | \ + BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | \ + BIT13 | BIT14 | BIT15 ) +#define CFG_PT_DIVIDER_CONSTANT ((double)(pow((double)2, (double)48) / (double)600)) + +/* Chip ID values */ +#define CFG_CID_ROUTER_ASIC (0) /* SpaceWire Router ASIC and IP */ +#define CFG_CID_ROUTER_USB (1) /* Original SpaceWire Router-USB */ +#define CFG_CID_USB_BRICK (2) /* SpaceWire-USB Brick */ +#define CFG_CID_FEIC (4) /* The FEIC chip */ +#define CFG_CID_ROUTER_USB_2 (5) /* New SpaceWire Router-USB */ +#define CFG_CID_PCI_MK2 (7) /* SpaceWire PCI Mk2 */ +#define CFG_CID_PCI_EXPRESS (8) /* SpaceWire PCI Express */ +#define CFG_CID_RTC (9) /* RTC Development Unit */ +#define CFG_CID_CONFORMANCE_TESTER (10) /* SpaceWire Conformance Tester */ +#define CFG_CID_EGSE (11) /* SpaceWire EGSE */ +#define CFG_CID_STAR_FIRE (12) /* STAR Fire */ +#define CFG_CID_WBS_MK2 (14) /* WBS Mk2 */ + + +/* Addresses which can be read from and written to */ +#define CFG_EXTENDED_ADDRESS (0x100) +#define CFG_ADDR_NET_DISC (CFG_EXTENDED_ADDRESS + 0) +#define CFG_ADDR_NET_DISC_IDENT (CFG_EXTENDED_ADDRESS + 1) +#define CFG_ADDR_ROUTER_CONTROL (CFG_EXTENDED_ADDRESS + 2) +#define CFG_ADDR_ERRORS (CFG_EXTENDED_ADDRESS + 3) +#define CFG_ADDR_TIMECODE (CFG_EXTENDED_ADDRESS + 4) +#define CFG_ADDR_IDS (CFG_EXTENDED_ADDRESS + 5) +#define CFG_ADDR_GP (CFG_EXTENDED_ADDRESS + 6) +#define CFG_ADDR_TICK (CFG_EXTENDED_ADDRESS + 7) +#define CFG_ADDR_TX_RATE (CFG_EXTENDED_ADDRESS + 8) +#define CFG_ADDR_PRECISION_1 (CFG_EXTENDED_ADDRESS + 0xC) +#define CFG_ADDR_PRECISION_2 (CFG_EXTENDED_ADDRESS + 0xD) + + +/* Exported functions */ + +/* Version information */ +ROUTER_CONFIG_LIBRARY double ROUTER_CONFIG_CC CFGSpaceWire_GetAPIVersion(void); + +/* Configuration address stack manipulation functions */ +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_StackClear(void); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_AddrStackPush( + U8 dwAddress); +ROUTER_CONFIG_LIBRARY U8 ROUTER_CONFIG_CC CFGSpaceWire_AddrStackPop(void); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RetAddrStackPush( + U8 dwAddress); +ROUTER_CONFIG_LIBRARY U8 ROUTER_CONFIG_CC CFGSpaceWire_RetAddrStackPop(void); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_SetProtocolByte( + U8 ProtocolByte); +ROUTER_CONFIG_LIBRARY U8 ROUTER_CONFIG_CC CFGSpaceWire_GetProtocolByte(void); + +/* RMAP functions */ +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_EnableRMAP( + char useRMAP); +ROUTER_CONFIG_LIBRARY char ROUTER_CONFIG_CC CFGSpaceWire_IsRMAPEnabled(); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_SetRMAPDestinationKey( + U8 destinationKey); +ROUTER_CONFIG_LIBRARY U8 ROUTER_CONFIG_CC CFGSpaceWire_GetRMAPDestinationKey(); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_SetRMAPAlignment( + U8 alignment); +ROUTER_CONFIG_LIBRARY U8 ROUTER_CONFIG_CC CFGSpaceWire_GetRMAPAlignment(); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_EnableReceiveOnAllPorts(char enable); +ROUTER_CONFIG_LIBRARY char ROUTER_CONFIG_CC + CFGSpaceWire_IsReceiveOnAllPortsEnabled(); + +/* Ignoring replies to write commands functions */ +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_IgnoreWriteReplies( + char ignore); +ROUTER_CONFIG_LIBRARY char ROUTER_CONFIG_CC + CFGSpaceWire_AreWriteRepliesIgnored(); + +/* Configuration address read and write functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_ReadAddress( + star_device_handle hDevice, U32 dwAddress, U32 *dwData); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_WriteAddress( + star_device_handle hDevice, U32 dwAddress, U32 dwData); + +/* Router link functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_StartLink( + star_device_handle hDevice, U32 dwLinkNum); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_StopLink( + star_device_handle hDevice, U32 dwLinkNum); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_TriStateLink( + star_device_handle hDevice, U32 dwLinkNum, char bEnabled); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetLinkSpeed( + star_device_handle hDevice, U32 dwLinkNum, U32 dwSpeed); + +/* Routing table functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetRoutingTableEntry( + star_device_handle hDevice, U32 nLogicalAddress, U32 *dwRoutingTableEntry); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetRoutingTableEntry( + star_device_handle hDevice, U32 nLogicalAddress, U32 dwRoutingTableEntry); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_ClearRoutingTableEntry( + star_device_handle hDevice, U32 nLogicalAddress); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RTIsEnabled( + U32 dwRoutingTableEntry, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RTIsDelHead( + U32 dwRoutingTableEntry, char *bDelHead); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RTIsPriority( + U32 dwRoutingTableEntry, char *bPriority); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RTOutputPorts( + U32 dwRoutingTableEntry, U32 *dwOutputPorts); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RTGetOutputPorts( + U32 dwRoutingTableEntry, U32 *dwOutputPorts); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_RTBuildRoutingTableEntry(U32 *dwRoutingTableEntry, + U32 dwOutputPorts, char bDelHead, char bPriority); + +/* Link status control functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetLinkStatusControl( + star_device_handle hDevice, U32 dwLinkNum, U32 *dwStatusControl); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetLinkStatusControl( + star_device_handle hDevice, U32 dwLinkNum, U32 dwStatusControl); + +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSErrorStatus( + U32 dwStatusControl, U32 *dwErrorStatus); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSConfigErrorStatus( + U32 dwStatusControl, U32 *dwErrorStatus); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSExternalErrorStatus( + U32 dwStatusControl, U32 *dwErrorStatus); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSLinkState( + U32 dwStatusControl, U32 *dwLinkStatus); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSIsLinkRunning( + U32 dwStatusControl, char *isLinkRunning); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSIsAutoStart( + U32 dwStatusControl, char *isAutoStart); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSEnableAutoStart( + U32 *dwStatusControl, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSIsStart( + U32 dwStatusControl, char *isStart); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSEnableStart( + U32 *dwStatusControl, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSIsDisabled( + U32 dwStatusControl, char *isDisabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSEnableDisabled( + U32 *dwStatusControl, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSIsTristate( + U32 dwStatusControl, char *isTristate); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSEnableTristate( + U32 *dwStatusControl, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSOperatingSpeed( + U32 dwStatusControl, U32 *dwOperatingSpeed); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSSetOperatingSpeed( + U32 *dwStatusControl, U32 dwOperatingSpeed); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSOutputPortConnection( + U32 dwStatusControl, U32 *dwOutputPortConnection); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_LSPortType( + U32 dwStatusControl, U32 *dwPortType); + +/* Network discovery information retreival */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetNetworkDiscoveryValue(star_device_handle hDevice, + U32 *dwNetworkDiscovery); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_NDDeviceType( + U32 dwNetDisc, U32 *dwDeviceType); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_NDReturnPort( + U32 dwNetDisc, U32 *dwReturnPort); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_NDRunningLinks( + U32 dwNetDisc, U32 *dwRunningLinks); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_NDNumberLinks( + U32 dwNetDisc, U32 *dwNumberLinks); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetNumberLinks( + star_device_handle hDevice, U32 *dwNumLinks); + +/* Router identity register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetNetworkID( + star_device_handle hDevice, U32 dwNetworkID); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetNetworkID( + star_device_handle hDevice, U32 *dwNetworkID); + +/* Router control register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetPortTimeout( + star_device_handle hDevice, char bEnabled, + CFG_SPACEWIRE_PORT_TIMEOUT timeout); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetPortTimeout( + star_device_handle hDevice, char *bEnabled, + CFG_SPACEWIRE_PORT_TIMEOUT *timeout); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_IsPortTimeoutEnabled( + star_device_handle hDevice, char *bEnabled); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetAsInterface( + star_device_handle hDevice, char bEnabled, char bAddIdentifier); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetRouterControlRegister(star_device_handle hDevice, + U32 *dwRouterCtrlReg); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_SetRouterControlRegister(star_device_handle hDevice, + U32 dwRouterCtrlReg); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetTimeoutEnabled( + U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetTimeoutEnabled( + U32 *dwRouterCtrlReg, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetTimeoutSelection( + U32 dwRouterCtrlReg, U32 *dwSelection); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetTimeoutSelection( + U32 *dwRouterCtrlReg, U32 dwSelection); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetDisableOnSilence( + U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetDisableOnSilence( + U32 *dwRouterCtrlReg, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetStartOnRequest( + U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetStartOnRequest( + U32 *dwRouterCtrlReg, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetSelfAddressing( + U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetSelfAddressing( + U32 *dwRouterCtrlReg, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCGetInterface( + U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_RCSetInterface( + U32 *dwRouterCtrlReg, char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_RCGetInterfaceIdentifier(U32 dwRouterCtrlReg, char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_RCSetInterfaceIdentifier(U32 *dwRouterCtrlReg, char bEnabled); + +/* Error active register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetErrorStatus( + star_device_handle hDevice, U32 *dwErrorStatus); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_ClearErrorStatus( + star_device_handle hDevice, U32 dwPorts); + +/* Time-Code register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetTimecodeRegister( + star_device_handle hDevice, U32 *dwTimecodeReg); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_TCGetValue( + U32 dwTimecodeReg, U32 *dwValue); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_TCGetFlags( + U32 dwTimecodeReg, U32 *dwValue); + +/* Manufacturer and Chip ID register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetIDRegister( + star_device_handle hDevice, U32 *dwIDs); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_IDGetManufacturer( + U32 dwIDs, U32 *dwManufacturerID); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_IDGetChipID(U32 dwIDs, + U32 *dwChipID); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC CFGSpaceWire_IDGetVersion(U32 dwIDs, + U32 *dwVersion); + +/* General purpose register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetGeneralPurposeStatus( + star_device_handle hDevice, U32 *dwGeneralPurposeStatus); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetGeneralPurposeStatus( + star_device_handle hDevice, U32 dwGeneralPurposeStatus); + +/* Tick enable register functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_GetTickEnableStatus( + star_device_handle hDevice, U32 *dwTickEnableStatus); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC CFGSpaceWire_SetTickEnableStatus( + star_device_handle hDevice, U32 dwTickEnableStatus); + + +/* Base Transmit Rate functions */ +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_SetRouterBaseTransmitRate(star_device_handle hDevice, + U32 dwBaseClkSel); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetRouterBaseTransmitRate(star_device_handle hDevice, + U32 *dwBaseClkSel); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_SetBrickBaseTransmitRate(star_device_handle hDevice, + U32 dwBaseClk, U32 dwBaseDvdr, U32 dwEnableClk); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetBrickBaseTransmitRate(star_device_handle hDevice, + U32 *dwBaseClk, U32 *dwBaseDvdr, U32 *dwEnableClk); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetPrecisionTransmitRegister(star_device_handle hDevice, + U32 *dwPrecisionTransmit); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_SetPrecisionTransmitRegister(star_device_handle hDevice, + U32 dwPrecisionTransmit); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_PTGetPrecisionTransmitEnabled(U32 dwPrecisionTransmit, + char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_PTSetPrecisionTransmitEnabled(U32 *dwPrecisionTransmit, + char bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_PTGetPrecisionTransmitReady(U32 dwPrecisionTransmit, + char *bEnabled); +ROUTER_CONFIG_LIBRARY void ROUTER_CONFIG_CC + CFGSpaceWire_PTGetPrecisionTransmitInUse(U32 dwPrecisionTransmit, + char *bEnabled); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_GetPrecisionTransmitRate(star_device_handle hDevice, + double *PrecisionTransmitRate); +ROUTER_CONFIG_LIBRARY int ROUTER_CONFIG_CC + CFGSpaceWire_SetPrecisionTransmitRate(star_device_handle hDevice, + double PrecisionTransmitRate); + + + +#ifdef __cplusplus +} +#endif + + + +#endif /* SPACEWIRE_ROUTER_LIBRARY */ + + + diff --git a/spw_usb_driver_v2.61/inc/spw_usb_api.h b/spw_usb_driver_v2.61/inc/spw_usb_api.h new file mode 100755 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/spw_usb_api.h @@ -0,0 +1,326 @@ +/******************************************************************************/ +/* */ +/* spw_usb_api.h */ +/* */ +/* Declaration of the functions provided by the SpaceWire USB API Library */ +/* for the SpaceWire USB devices. */ +/* */ +/* Version 2.61, September 21st 2012 */ +/* */ +/* Version 2.61, 21/09/12 */ +/* ====================== */ +/* Added support for STAR Fire and WBS II. */ +/* */ +/* Version 2.60, 04/01/12 */ +/* ====================== */ +/* Added support for EGSE and SPLT. */ +/* */ +/* Version 2.59, 15/08/11 */ +/* ====================== */ +/* Added support for RTC. */ +/* */ +/* Version 2.5, 12/10/10 */ +/* ===================== */ +/* Added support for Link Analyser Mk2. */ +/* */ +/* Version 1.5, 12/03/10 */ +/* ===================== */ +/* Added GetFirmwareVersionExtended and restored GetFirmwareVersion to */ +/* its original form. */ +/* */ +/* Version 1.4, 03/03/10 */ +/* ===================== */ +/* Fixed bug waiting on a receive to complete. */ +/* Added support for multiple send channels. */ +/* Added functions to get serial number and product ID. */ +/* */ +/* Version 1.3, 26/2/09 */ +/* ==================== */ +/* Updated the calling convention used in the function declaration to */ +/* __stdcall on Windows. */ +/* */ +/* Version 1.2, 21/1/09 */ +/* ==================== */ +/* Updated to compile on both Windows and Linux. */ +/* */ +/* Version 1.1, 8/10/06 */ +/* ==================== */ +/* Linux release. */ +/* */ +/* Version 1.0, 24/4/06 */ +/* ==================== */ +/* Initial version. */ +/* */ +/* Copyright (2012), STAR-Dundee Ltd., */ +/* STAR House, */ +/* 166 Nethergate, */ +/* Dundee, DD1 4EE, */ +/* Scotland, UK. */ +/* e-mail: support@star-dundee.com */ +/* */ +/******************************************************************************/ + + + +#ifndef SPACEWIRE_USB_API_H +#define SPACEWIRE_USB_API_H + + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#include "spacewire_usb.h" + + + +#if defined(_WIN32) || defined(_WIN64) + + +/* Windows specifc functions and macros */ + +#ifdef SPACEWIREUSBAPI_EXPORTS +#define SPACEWIREUSB_API __declspec(dllexport) +#else +#define SPACEWIREUSB_API __declspec(dllimport) +#endif + +#ifdef _WIN64 +#define SPW_USB_API_CC +#else +#define SPW_USB_API_CC __stdcall +#endif /* WIN64 */ + + +#include "windows.h" + + +#else /* _WIN32 */ + + +/* Linux specific functions and macros */ + +#define SPACEWIREUSB_API +#define SPW_USB_API_CC + + +#endif /* _WIN32 */ + + + +/* Functions provided by the API */ + +/* General functions */ +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_Open( + star_device_handle *phDevice, int nDeviceNum); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_Close( + star_device_handle hDevice); +SPACEWIREUSB_API U8 SPW_USB_API_CC USBSpaceWire_CountDevices(); +SPACEWIREUSB_API U32 SPW_USB_API_CC USBSpaceWire_ListDevices(); +SPACEWIREUSB_API double SPW_USB_API_CC USBSpaceWire_GetDriverVersion(); +SPACEWIREUSB_API double SPW_USB_API_CC USBSpaceWire_GetIFVersion(); +SPACEWIREUSB_API double SPW_USB_API_CC USBSpaceWire_GetAPIVersion(); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_SetTimeout( + star_device_handle hDevice, double timeout); +SPACEWIREUSB_API double SPW_USB_API_CC USBSpaceWire_GetTimeout( + star_device_handle hDevice); +SPACEWIREUSB_API U8 SPW_USB_API_CC USBSpaceWire_GetSpaceWireAddress( + star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_SetSpaceWireAddress( + star_device_handle hDevice, U8 address); +SPACEWIREUSB_API U16 SPW_USB_API_CC USBSpaceWire_GetFirmwareVersion( + star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_GetFirmwareVersionExtended( + star_device_handle hDevice, SPACEWIRE_FIRMWARE_VERSION *pVersion); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_ClearEndpoints( + star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_ResetDevice( + star_device_handle hDevice); +SPACEWIREUSB_API SPACEWIRE_DEVICE_TYPE SPW_USB_API_CC + USBSpaceWire_GetDeviceType(star_device_handle hDevice); +SPACEWIREUSB_API SPACEWIRE_DEVICE_TYPE SPW_USB_API_CC + USBSpaceWire_GetUnopenedDeviceType(int deviceNum); +SPACEWIREUSB_API U16 SPW_USB_API_CC USBSpaceWire_GetDeviceProductID( + star_device_handle hDevice); +SPACEWIREUSB_API U16 SPW_USB_API_CC USBSpaceWire_GetUnopenedDeviceProductID( + int deviceNum); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_EnableHeaderMode( + star_device_handle hDevice, char enable); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_IsHeaderModeEnabled( + star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_EnableNetworkMode( + star_device_handle hDevice, char enable); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_IsNetworkModeEnabled( + star_device_handle hDevice); +SPACEWIREUSB_API double SPW_USB_API_CC USBSpaceWire_GetUSBVersion( + star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_GetAPIString(char *str); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_GetSerialNumber( + star_device_handle hDevice, U8 pSerialNumber[11]); + +/* Receive functions */ +SPACEWIREUSB_API unsigned long SPW_USB_API_CC + USBSpaceWire_GetDriverDroppedPackets(star_device_handle hDevice); +SPACEWIREUSB_API unsigned long SPW_USB_API_CC + USBSpaceWire_GetDriverDroppedBytes(star_device_handle hDevice); +SPACEWIREUSB_API unsigned long SPW_USB_API_CC USBSpaceWire_GetDroppedPackets( + star_device_handle hDevice); +SPACEWIREUSB_API unsigned long SPW_USB_API_CC USBSpaceWire_GetDroppedBytes( + star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_RegisterReceiveOnPort( + star_device_handle hDevice, U8 port); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_UnregisterReceiveOnPort( + star_device_handle hDevice, U8 port); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_RegisterReceiveOnAllPorts( + star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_UnregisterReceiveOnAllPorts( + star_device_handle hDevice); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC USBSpaceWire_ReadPackets( + star_device_handle hDevice, void *pBuffer, U32 nBufferSize, + U32 nPacketNum, char bWait, PUSB_SPACEWIRE_PACKET_PROPERTIES properties, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_FreeRead( + star_device_handle hDevice, USB_SPACEWIRE_ID identifier); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_FreeAllReads( + star_device_handle hDevice); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC USBSpaceWire_GetReadStatus( + star_device_handle hDevice, USB_SPACEWIRE_ID identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_WaitOnReadCompleting(star_device_handle hDevice, + USB_SPACEWIRE_ID identifier, char bWaitIndefinitely); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_EnableReadThrottling( + star_device_handle hDevice, char enable); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_IsReadThrottling( + star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_SetDriverReadBufferSize( + star_device_handle hDevice, unsigned long nBufferSize); +SPACEWIREUSB_API unsigned long SPW_USB_API_CC + USBSpaceWire_GetDriverReadBufferSize(star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_SetDriverReadStructsNum( + star_device_handle hDevice, unsigned long nStructsNum); +SPACEWIREUSB_API unsigned long SPW_USB_API_CC + USBSpaceWire_GetDriverReadStructsNum(star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_WaitOnReadPacketAvailable( + star_device_handle hDevice, double timeout); +SPACEWIREUSB_API U32 SPW_USB_API_CC USBSpaceWire_GetReadLength( + PUSB_SPACEWIRE_PACKET_PROPERTIES pProperties, U32 nPacketNum); +SPACEWIREUSB_API USB_SPACEWIRE_EOP_TYPE SPW_USB_API_CC + USBSpaceWire_GetReadEOPStatus(PUSB_SPACEWIRE_PACKET_PROPERTIES pProperties, + U32 nPacketNum); +SPACEWIREUSB_API SPACEWIRE_TRAFFIC_TYPE SPW_USB_API_CC + USBSpaceWire_GetReadTrafficType( + PUSB_SPACEWIRE_PACKET_PROPERTIES pProperties, U32 nPacketNum); + +/* Send functions */ +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_GetNumberOfSendChannels( + star_device_handle hDevice); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC USBSpaceWire_SendPacketTo( + star_device_handle hDevice, void *pBuffer, U32 nBufferSize, + U8 *pAddress, U32 nAddressLen, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendPacketToOverChannel(star_device_handle hDevice, U8 channel, + void *pBuffer, U32 nBufferSize, U8 *pAddress, U32 nAddressLen, + char bWait, USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketsTo(star_device_handle hDevice, + void *pBuffer, U32 nPacketSize, U32 nBufferSize, U8 *pAddress, + U32 nAddressLen, char bWait, USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketsToOverChannel(star_device_handle hDevice, + U8 channel, void *pBuffer, U32 nPacketSize, U32 nBufferSize, + U8 *pAddress, U32 nAddressLen, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketLengthsTo(star_device_handle hDevice, + void **pBuffers, U32 *pPacketSizes, U32 nNumberOfPackets, U8 *pAddress, + U32 nAddressLen, char bWait, USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketLengthsToOverChannel( + star_device_handle hDevice, U8 channel, void **pBuffers, + U32 *pPacketSizes, U32 nNumberOfPackets, U8 *pAddress, U32 nAddressLen, + char bWait, USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC USBSpaceWire_SendPacket( + star_device_handle hDevice, void *pBuffer, U32 nBufferSize, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendPacketOverChannel(star_device_handle hDevice, U8 channel, + void *pBuffer, U32 nBufferSize, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePackets(star_device_handle hDevice, void *pBuffer, + U32 nPacketSize, U32 nBufferSize, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketsOverChannel(star_device_handle hDevice, + U8 channel, void *pBuffer, U32 nPacketSize, U32 nBufferSize, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketLengths(star_device_handle hDevice, + void **pBuffers, U32 *pPacketSizes, U32 nNumberOfPackets, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_SendMultiplePacketLengthsOverChannel( + star_device_handle hDevice, U8 channel, void **pBuffers, + U32 *pPacketSizes, U32 nNumberOfPackets, char bWait, + USB_SPACEWIRE_ID *identifier); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_FreeSend( + star_device_handle hDevice, USB_SPACEWIRE_ID identifier); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_FreeAllSends( + star_device_handle hDevice); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC USBSpaceWire_GetSendStatus( + star_device_handle hDevice, USB_SPACEWIRE_ID identifier); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_WaitOnSendCompleting(star_device_handle hDevice, + USB_SPACEWIRE_ID identifier, char bWaitIndefinitely); +SPACEWIREUSB_API U32 SPW_USB_API_CC USBSpaceWire_GetSendSize( + star_device_handle hDevice, USB_SPACEWIRE_ID identifier); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_SetDriverSendBufferSize( + star_device_handle hDevice, U32 nBufferSize); +SPACEWIREUSB_API U32 SPW_USB_API_CC USBSpaceWire_GetDriverSendBufferSize( + star_device_handle hDevice); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_EnableSendEEPs( + star_device_handle hDevice, char enable); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_IsSendEEPsEnabled( + star_device_handle hDevice); +SPACEWIREUSB_API USB_SPACEWIRE_STATUS SPW_USB_API_CC + USBSpaceWire_TunnelSendTraffic(star_device_handle hDevice, + SPACEWIRE_TRAFFIC_TYPE type, void *pBuffer, U32 nBufferSize, + USB_SPACEWIRE_EOP_TYPE eop, U8 port, char bWait, + USB_SPACEWIRE_ID *identifier); + +/* Time-code functions */ +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_TC_PerformTickIn( + star_device_handle hDevice, U8 timein); +SPACEWIREUSB_API char SPW_USB_API_CC + USBSpaceWire_TC_EnableExternalTimecodeSelection(star_device_handle hDevice, + char enable); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_TC_Reset( + star_device_handle hDevice); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_TC_EnableAutoTickIn( + star_device_handle hDevice, char enableAutoTickIns, char enableAllPorts); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_TC_SetAutoTickInFrequency( + star_device_handle hDevice, U32 frequency); +SPACEWIREUSB_API char SPW_USB_API_CC USBSpaceWire_TC_StartReadingTimecodes( + star_device_handle hDevice, void *arg, void (*callbackfunc)( + star_device_handle hDevice, U8 timecode, void *arg)); +SPACEWIREUSB_API void SPW_USB_API_CC USBSpaceWire_TC_StopReadingTimecodes( + star_device_handle hDevice); +SPACEWIREUSB_API U32 SPW_USB_API_CC USBSpaceWire_TC_GetClockFrequency( + star_device_handle hDevice); + + + +#ifdef __cplusplus +} +#endif + + + +#endif /* SPACEWIRE_USB_API_H */ + + diff --git a/spw_usb_driver_v2.61/inc/star-dundee_types.h b/spw_usb_driver_v2.61/inc/star-dundee_types.h new file mode 100644 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/star-dundee_types.h @@ -0,0 +1,161 @@ +/** + * \file star-dundee_types.h + * \brief Definitions of STAR-Dundee commonly used types. + * \author Stuart Mills\n + * STAR-Dundee\n + * c/o School of Computing\n + * University of Dundee\n + * Dundee, DD1 4HN\n + * Scotland, UK\n + * e-mail: support@star-dundee.com + * + * This file contains the definitions of common types used by STAR-Dundee + * software drivers and APIs. + * + * IMPORTANT NOTE: + * \note If you are experiencing compilation errors indicating that + * U8 is already defined, for example, please add the following + * line to your code prior to including this file:\n + * \#define NO_STAR_TYPES\n + * Alternatively you can compile your code with a flag of + * -DNO_STAR_TYPES.\n + * + * \version 1.1 - August 22nd 2011\n + * Removed star_device_handle, not required by STAR-System.\n\n + * + * \version 1.0 - March 22nd 2007\n + * Initial version.\n\n + * + * Copyright © 2009 STAR-Dundee Ltd + */ + + +/** + * \defgroup STARDundeeTypes STAR-Dundee Types + * This section contains the definitions of types used in STAR-Dundee software + * drivers and APIs. + */ + +/** + * \def TRUE + * \ingroup STARDundeeTypes + * A value that can be used to represent the boolean value of true. + */ + +/** + * \def FALSE + * \ingroup STARDundeeTypes + * A value that can be used to represent the boolean value of false. + */ + +/** + * \typedef U8 + * \ingroup STARDundeeTypes + * A type that can be used to represent an unsigned 8-bit number. + */ + +/** + * \typedef U16 + * \ingroup STARDundeeTypes + * A type that can be used to represent an unsigned 16-bit number. + */ + +/** + * \typedef U32 + * \ingroup STARDundeeTypes + * A type that can be used to represent an unsigned 32-bit number. + */ + +/** + * \typedef REGISTER + * \ingroup STARDundeeTypes + * A type that can be used to represent a 4-byte register. + */ + + +#ifndef STAR_DUNDEE_TYPES +#define STAR_DUNDEE_TYPES + +/* Define TRUE and FALSE */ +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef NO_STAR_TYPES + +#if (defined(__linux__) || defined(LINUX) || defined(__LINUX__) || \ + defined(__CYGWIN__)) && defined(__KERNEL__) + + #include + + /* Define U8, U16 and U32 in the Linux kernel */ + #ifndef U8 + typedef u8 U8; + #endif + #ifndef U16 + typedef u16 U16; + #endif + #ifndef U32 + typedef u32 U32; + #endif + +#else + + #include + + /* Define U8 */ + #ifndef U8 + #if (UCHAR_MAX == 0xff) + typedef unsigned char U8; + #elif (UINT_MAX == 0xff) + typedef unsigned int U8; + #else + #error "No valid definition of U8 available" + #endif + #endif + + /* Define U16 */ + #ifndef U16 + #if (USHRT_MAX == 0xffff) + typedef unsigned short U16; + #elif (UINT_MAX == 0xffff) + typedef unsigned int U16; + #elif (UCHAR_MAX == 0xffff) + typedef unsigned char U16; + #else + #error "No valid definition of U16 available" + #endif + #endif + + /* Define U32 */ + #ifndef U32 + #if (UINT_MAX == 0xffffffff) + typedef unsigned int U32; + #elif (ULONG_MAX == 0xffffffff) + typedef unsigned long U32; + #elif (USHRT_MAX == 0xffffffff) + typedef unsigned short U32; + #elif (UCHAR_MAX == 0xffffffff) + typedef unsigned char U32; + #else + #error "No valid definition of U32 available" + #endif + #endif + +#endif /* Linux kernel test */ + + +#endif /* NO_STAR_TYPES */ + +/* Define REGISTER */ +#ifndef REGISTER + typedef U32 REGISTER; +#endif + + +#endif /* STAR_DUNDEE_TYPES */ + + diff --git a/spw_usb_driver_v2.61/inc/star_dundee_types.h b/spw_usb_driver_v2.61/inc/star_dundee_types.h new file mode 100755 --- /dev/null +++ b/spw_usb_driver_v2.61/inc/star_dundee_types.h @@ -0,0 +1,97 @@ +/******************************************************************************/ +/* */ +/* star_dundee_types.h */ +/* */ +/* This file contains the definitions of common types used by STAR-Dundee */ +/* drivers and APIs. */ +/* */ +/* IMPORTANT NOTE: If you are experiencing compilation errors indicating */ +/* that U8 is already defined, for example, please add the */ +/* following line to your code prior to including this */ +/* file: */ +/* #define NO_STAR_TYPES */ +/* Alternatively you can compile your code with a flag of */ +/* -DNO_STAR_TYPES. */ +/* */ +/* Version 1.0, March 22nd 2007 */ +/* */ +/* Version 1.0 - March 22nd 2007 */ +/* =========== */ +/* Initial version. */ +/* */ +/* Copyright (2012), STAR-Dundee Ltd., */ +/* STAR House, */ +/* 166 Nethergate, */ +/* Dundee, DD1 4EE, */ +/* Scotland, UK. */ +/* e-mail: support@star-dundee.com */ +/* */ +/******************************************************************************/ + + + +#ifndef STAR_DUNDEE_TYPES +#define STAR_DUNDEE_TYPES + + +typedef void *star_device_handle; + + +#ifndef NO_STAR_TYPES + +#if (defined(__linux__) || defined(LINUX) || defined(__LINUX__)) && \ + defined(__KERNEL__) + + #include + + /* Define U8, U16 and U32 in the Linux kernel */ + typedef u8 U8; + typedef u16 U16; + typedef u32 U32; + +#else + + #include + + /* Define U8 */ + #if (UCHAR_MAX == 0xff) + typedef unsigned char U8; + #elif (UINT_MAX == 0xff) + typedef unsigned int U8; + #else + #error "No valid definition of U8 available" + #endif + + /* Define U16 */ + #if (USHRT_MAX == 0xffff) + typedef unsigned short U16; + #elif (UINT_MAX == 0xffff) + typedef unsigned int U16; + #elif (UCHAR_MAX == 0xffff) + typedef unsigned char U16; + #else + #error "No valid definition of U16 available" + #endif + + /* Define U32 */ + #if (UINT_MAX == 0xffffffff) + typedef unsigned int U32; + #elif (ULONG_MAX == 0xffffffff) + typedef unsigned long U32; + #elif (USHRT_MAX == 0xffffffff) + typedef unsigned short U32; + #elif (UCHAR_MAX == 0xffffffff) + typedef unsigned char U32; + #else + #error "No valid definition of U32 available" + #endif + +#endif /* Linux kernel test */ + + +#endif /* NO_STAR_TYPES */ + + +#endif /* STAR_DUNDEE_TYPES */ + + diff --git a/spw_usb_driver_v2.61/lib/i386/spacewire_cuba_software b/spw_usb_driver_v2.61/lib/i386/spacewire_cuba_software new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b688714265809f1a96871a0774c9e91bf18f3075 GIT binary patch literal 71192 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 U^D@uOWQ2^ZfrcouK$&g)AKz(7nE(I) diff --git a/spw_usb_driver_v2.61/lib/x86_64/spacewire_cuba_software b/spw_usb_driver_v2.61/lib/x86_64/spacewire_cuba_software new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4058ad6f47b920a85413bd85f6826d3599014a53 GIT binary patch literal 80878 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 Ee?JjWr~m)}