This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,410 @@
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkAdjustment" id="adjustment1">
<property name="value">1</property>
<property name="lower">1</property>
<property name="upper">8</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="adjustment2">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="adjustment3">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkListStore" id="model1">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">unspecified</col>
</row>
<row>
<col id="0" translatable="yes">female</col>
</row>
<row>
<col id="0" translatable="yes">male</col>
</row>
<row>
<col id="0" translatable="yes">unknown</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model2">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">/dev/rfcomm0</col>
</row>
<row>
<col id="0" translatable="yes">/dev/rfcomm1</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model3">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">256</col>
</row>
</data>
</object>
<object class="GtkDialog" id="openvibe-acquisition-server-settings">
<property name="border_width">5</property>
<property name="title" translatable="yes">Device configuration</property>
<property name="window_position">center</property>
<property name="type_hint">dialog</property>
<property name="gravity">center</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
<property name="spacing">8</property>
<child>
<object class="GtkLabel" id="label_title">
<property name="visible">True</property>
<property name="label" translatable="yes">g.Tec gMobi Lab+</property>
<property name="justify">center</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox">
<property name="visible">True</property>
<property name="border_width">8</property>
<property name="spacing">8</property>
<child>
<object class="GtkHBox" id="hbox">
<property name="visible">True</property>
<property name="spacing">8</property>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">0</property>
<property name="adjustment">adjustment1</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_number_of_channels">
<property name="visible">True</property>
<property name="label" translatable="yes">Number of channels :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_gender">
<property name="visible">True</property>
<property name="model">model1</property>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_age">
<property name="visible">True</property>
<property name="label" translatable="yes">Age :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_gender">
<property name="visible">True</property>
<property name="label" translatable="yes">Gender :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spinbutton_age">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment2</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spinbutton_identifier">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment3</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_identifier">
<property name="visible">True</property>
<property name="label" translatable="yes">Identifier :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label_port">
<property name="visible">True</property>
<property name="xpad">5</property>
<property name="ypad">5</property>
<property name="label" translatable="yes">Port name :</property>
<property name="justify">center</property>
<property name="selectable">True</property>
<property name="width_chars">10</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_port">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="text" translatable="yes">/dev/rfcomm0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_testmode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Use test mode :</property>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton_testmode">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<!--
<child>
<object class="GtkComboBoxEntry" id="combobox_port">
<property name="visible">True</property>
<property name="model">model2</property>
<property name="active">1</property>
<property name="button_sensitivity">on</property>
<property name="text_column">0</property>
<child>
<object class="GtkCellRendererText" id="renderer2"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
-->
<child>
<object class="GtkComboBox" id="combobox_sampling_frequency">
<property name="visible">True</property>
<property name="model">model3</property>
<child>
<object class="GtkCellRendererText" id="renderer3"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_sampling_frequency">
<property name="visible">True</property>
<property name="label" translatable="yes">Sampling frequency :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_change_channel_names">
<property name="label" translatable="yes">Change channel names...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">4</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button_apply">
<property name="label">gtk-apply</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_cancel">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-10">button_apply</action-widget>
<action-widget response="-6">button_cancel</action-widget>
</action-widgets>
</object>
</interface>
@@ -0,0 +1,14 @@
To use the gTec gMOBIlab+ device, it is necessary to connect it via Blutooth to the computer.
First the computer has to recognize the new peripheral (the gTec gMOBIlab+) and then the computer has to be connected to it.
The command on linux is :
rfcomm connect # xx:xx:xx:xx:xx:xx
Where # has to be replaced by a port number (0 if you want to connect to /dev/rfcomm0) and xx:xx:xx:xx:xx:xx is the mac address of the gTec module.
Once the device is connected, the OpenViBE-aquisition-server file can be run. A pop up appears with a menu containing "gTec gMOBIlab+", that has to be selected.
After checking in the properties that the port name is the same as the one you are connected to (default name is /dev/rfcomm0), it is possible to try to connect.
If the connection to the server fails, the state of the gMOBIlab+ should be checked : the diode of the gMOBIlab+ device should flash on and off.
The frequency of the gTecMobiLab+ is 256 Hz.
@@ -0,0 +1,46 @@
/**
* The gMobilab driver was contributed
* by Lucie Daubigney from Supelec Metz
*/
#include "ovasCConfigurationGTecGMobiLabPlus.h"
#if defined TARGET_HAS_ThirdPartyGMobiLabPlusAPI
namespace OpenViBE {
namespace AcquisitionServer {
CConfigurationGTecGMobiLabPlus::CConfigurationGTecGMobiLabPlus(const char* gtkBuilderFilename, std::string& portName, bool& testMode)
: CConfigurationBuilder(gtkBuilderFilename), m_portName(portName), m_testMode(testMode) {}
bool CConfigurationGTecGMobiLabPlus::preConfigure()
{
if (!CConfigurationBuilder::preConfigure()) { return false; }
GtkEntry* port = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_port"));
gtk_entry_set_text(port, m_portName.c_str());
GtkToggleButton* testMode = GTK_TOGGLE_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_testmode"));
gtk_toggle_button_set_active(testMode, m_testMode);
return true;
}
bool CConfigurationGTecGMobiLabPlus::postConfigure()
{
if (m_applyConfig)
{
GtkEntry* port = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_port"));
m_portName = gtk_entry_get_text(port);
GtkToggleButton* testMode = GTK_TOGGLE_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_testmode"));
m_testMode = (gtk_toggle_button_get_active(testMode) > 0);
}
return CConfigurationBuilder::postConfigure();
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGMobiLabPlusAPI
@@ -0,0 +1,37 @@
/**
* The gMobilab driver was contributed
* by Lucie Daubigney from Supelec Metz
*/
#pragma once
#include "../ovasCConfigurationBuilder.h"
#if defined TARGET_HAS_ThirdPartyGMobiLabPlusAPI
// #ifdef TARGET_OS_Windows
// #include <Windows.h>
// #endif
#include <gtk/gtk.h>
namespace OpenViBE {
namespace AcquisitionServer {
class CConfigurationGTecGMobiLabPlus final : public CConfigurationBuilder
{
public:
CConfigurationGTecGMobiLabPlus(const char* gtkBuilderFilename, std::string& portName, bool& testMode);
bool preConfigure() override;
bool postConfigure() override;
private:
std::string& m_portName;
bool& m_testMode;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGMobiLabPlusAPI
@@ -0,0 +1,432 @@
/**
* The gMobilab Linux driver was contributed by Lucie Daubigney from Supelec Metz
*
* Windows compatibility + gusbamp coexistence added by Jussi T. Lindgren / Inria
*
*/
#include "ovasCDriverGTecGMobiLabPlus.h"
#include "ovasCConfigurationGTecGMobiLabPlus.h"
#if defined TARGET_HAS_ThirdPartyGMobiLabPlusAPI
#include "ovasCDriverGTecGMobiLabPlusPrivate.h"
#include <toolkit/ovtk_all.h>
#include <system/ovCTime.h>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#if defined(TARGET_OS_Linux)
#include <dlfcn.h>
#endif
namespace OpenViBE {
namespace AcquisitionServer {
static const uint32_t N_ACQUIRED_CHANNEL = 8;
//constructor
CDriverGTecGMobiLabPlus::CDriverGTecGMobiLabPlus(IDriverContext& ctx)
: IDriver(ctx)
, m_settings("AcquisitionServer_Driver_GTecMobiLabPlus", m_driverCtx.getConfigurationManager())
, m_library(nullptr)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::CDriverGTecGMobiLabPlus\n";
m_gTec = new CDriverGTecGMobiLabPlusPrivate();
m_header = new CHeader();
m_header->setSamplingFrequency(256);
m_header->setChannelCount(8);
m_gTec->m_oBuffer.pBuffer = nullptr;
m_gTec->m_oBuffer.size = 0;
m_gTec->m_oBuffer.validPoints = 0;
#if defined(TARGET_OS_Windows)
m_portName = "//./COM1";
#else
m_portName="/dev/rfcomm0";
#endif
//initialisation of the analog channels of the gTec module : by default no analog exchange are allowed
m_gTec->m_analogIn.ain1 = false;
m_gTec->m_analogIn.ain2 = false;
m_gTec->m_analogIn.ain3 = false;
m_gTec->m_analogIn.ain4 = false;
m_gTec->m_analogIn.ain5 = false;
m_gTec->m_analogIn.ain6 = false;
m_gTec->m_analogIn.ain7 = false;
m_gTec->m_analogIn.ain8 = false;
m_settings.add("Header", m_header);
m_settings.add("PortName", &m_portName);
m_settings.add("TestMode", &m_testMode);
m_settings.load();
}
CDriverGTecGMobiLabPlus::~CDriverGTecGMobiLabPlus()
{
delete m_header;
delete m_gTec;
}
void CDriverGTecGMobiLabPlus::release()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::release\n";
delete this;
}
const char* CDriverGTecGMobiLabPlus::getName()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::getName\n";
return "g.tec gMOBIlab+";
}
//___________________________________________________________________//
// //
/*
* configuration
*/
bool CDriverGTecGMobiLabPlus::isConfigurable()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::isConfigurable\n";
return true;
}
bool CDriverGTecGMobiLabPlus::configure()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::configure\n";
// We use CConfigurationGTecMobilabPlus configuration which is a class that inheritate from the CConfigurationBuilder class
// The difference between these two classes is the addition of a member of class. This member allows to change the port where is connected the device.
CConfigurationGTecGMobiLabPlus config(Directories::getDataDir() + "/applications/acquisition-server/interface-GTec-GMobiLabPlus.ui", m_portName,
m_testMode);
// We configure the Header with it...
if (!config.configure(*m_header)) { return false; }
if (m_header->getChannelCount() > N_ACQUIRED_CHANNEL) { m_header->setChannelCount(N_ACQUIRED_CHANNEL); }
m_settings.save();
m_driverCtx.getLogManager() << Kernel::LogLevel_Debug << "Port name after configuration " << m_portName << " \n";
return true;
}
//___________________________________________________________________//
// //
#if defined(TARGET_OS_Linux)
#define GetProcAddress dlsym
#define FreeLibrary dlclose
#endif
bool CDriverGTecGMobiLabPlus::registerLibraryFunctions()
{
// Lets open the DLL
#if defined(TARGET_OS_Windows)
m_library = LoadLibrary("gMOBIlabplus.dll");
#else
m_library = dlopen("libgmobilabplusapi.so", RTLD_LAZY);
#endif
if (!m_library)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "CDriverGTecGMobiLabPlus:: Unable to open gMOBIlabplus.dll\n";
return false;
}
m_gTec->m_fOpenDevice = CDriverGTecGMobiLabPlusPrivate::OV_GT_OpenDevice(GetProcAddress(m_library, "GT_OpenDevice"));
m_gTec->m_fCloseDevice = CDriverGTecGMobiLabPlusPrivate::OV_GT_CloseDevice(GetProcAddress(m_library, "GT_CloseDevice"));
m_gTec->m_fSetTestmode = CDriverGTecGMobiLabPlusPrivate::OV_GT_SetTestmode(GetProcAddress(m_library, "GT_SetTestmode"));
m_gTec->m_fStartAcquisition = CDriverGTecGMobiLabPlusPrivate::OV_GT_StartAcquisition(GetProcAddress(m_library, "GT_StartAcquisition"));
m_gTec->m_fGetData = CDriverGTecGMobiLabPlusPrivate::OV_GT_GetData(GetProcAddress(m_library, "GT_GetData"));
m_gTec->m_fInitChannels = CDriverGTecGMobiLabPlusPrivate::OV_GT_InitChannels(GetProcAddress(m_library, "GT_InitChannels"));
m_gTec->m_fStopAcquisition = CDriverGTecGMobiLabPlusPrivate::OV_GT_StopAcquisition(GetProcAddress(m_library, "GT_StopAcquisition"));
m_gTec->m_fGetLastError = CDriverGTecGMobiLabPlusPrivate::OV_GT_GetLastError(GetProcAddress(m_library, "GT_GetLastError"));
m_gTec->m_fTranslateErrorCode = CDriverGTecGMobiLabPlusPrivate::OV_GT_TranslateErrorCode(GetProcAddress(m_library, "GT_TranslateErrorCode"));
if (!m_gTec->m_fOpenDevice || !m_gTec->m_fCloseDevice || !m_gTec->m_fSetTestmode
|| !m_gTec->m_fStartAcquisition || !m_gTec->m_fGetData || !m_gTec->m_fInitChannels
|| !m_gTec->m_fStopAcquisition || !m_gTec->m_fGetLastError || !m_gTec->m_fTranslateErrorCode)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "CDriverGTecGMobiLabPlus:: Unable to find all the required functions from the gMOBIlabplus.dll\n";
return false;
}
return true;
}
/*
* initialisation
*/
bool CDriverGTecGMobiLabPlus::initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::initialize\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Debug << "Port name after initialisation " << m_portName << "\n";
if (m_driverCtx.isConnected()) { return false; }
if (!m_header->isChannelCountSet() || !m_header->isSamplingFrequencySet())
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Either channel count or sampling frequency is not set\n";
return false;
}
if (!registerLibraryFunctions()) { return false; }
const size_t nChannel = m_header->getChannelCount();
// analog exchanges allowed on the first "nChannel" channels:
for (uint32_t i = 1; i <= nChannel; ++i) { allowAnalogInputs(i); }
// then buffer of type _BUFFER_ST built to store acquired samples.
m_gTec->m_oBuffer.pBuffer = new short int[nChannel
];//allocate enough space for the buffer m_oBuffer.pBuffer ; only one set of mesures is acquired (channel 1 to 8) in a row
m_gTec->m_oBuffer.size = nChannel * sizeof(short int);
m_gTec->m_oBuffer.validPoints = 0;
#if defined(TARGET_OS_Windows)
m_gTec->m_oOverlap.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_gTec->m_oOverlap.Offset = 0;
m_gTec->m_oOverlap.OffsetHigh = 0;
#endif
// allocates enough space for m_sample
m_sample = new float[nSamplePerSentBlock * nChannel];
// if there is a problem while creating the two arrays
if (!m_gTec->m_oBuffer.pBuffer || !m_sample)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Memory allocation problem\n";
delete [] m_gTec->m_oBuffer.pBuffer;
delete [] m_sample;
m_sample = nullptr;
m_gTec->m_oBuffer.pBuffer = nullptr;
return false;
}
// initializes hardware and get
// available header information
// from it
#if defined(TARGET_OS_Windows)
m_gTec->m_device = m_gTec->m_fOpenDevice(LPSTR(m_portName.c_str()));
#else
m_gTec->m_device = m_gTec->m_fOpenDevice(m_portName.c_str());
#endif
if (m_gTec->m_device == nullptr)
{
#if defined(TARGET_OS_Windows)
UINT errorCode = 0;
#else
uint32_t errorCode = 0;
#endif
_ERRSTR error;
m_gTec->m_fGetLastError(&errorCode);
m_gTec->m_fTranslateErrorCode(&error, errorCode);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Unable to connect to [" << m_portName << "], error code " << errorCode << ": '" << error.Error
<< "'\n";
delete [] m_gTec->m_oBuffer.pBuffer;
delete [] m_sample;
return false;
}
// saves parameters
m_callback = &callback;
m_nSamplePerSentBlock = nSamplePerSentBlock;
return true;
}
bool CDriverGTecGMobiLabPlus::uninitialize()
{
bool ok = true;
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::uninitialize\n";
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
// uninitializes hardware here
if (!m_gTec->m_fCloseDevice(m_gTec->m_device))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "GT_CloseDevice() failed\n";
ok = false;
}
// frees memory
delete [] m_sample;
delete [] m_gTec->m_oBuffer.pBuffer;
m_sample = nullptr;
m_gTec->m_oBuffer.pBuffer = nullptr;
m_callback = nullptr;
// uninitialisation of the analog channels : set valus to default ones
m_gTec->m_analogIn.ain1 = false;
m_gTec->m_analogIn.ain2 = false;
m_gTec->m_analogIn.ain3 = false;
m_gTec->m_analogIn.ain4 = false;
m_gTec->m_analogIn.ain5 = false;
m_gTec->m_analogIn.ain6 = false;
m_gTec->m_analogIn.ain7 = false;
m_gTec->m_analogIn.ain8 = false;
if (m_library)
{
FreeLibrary(m_library);
m_library = nullptr;
}
return ok;
}
const IHeader* CDriverGTecGMobiLabPlus::getHeader() { return m_header; }
//___________________________________________________________________//
// //
/*
* acquisition
*/
bool CDriverGTecGMobiLabPlus::start()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::start\n";
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
// we use none of the digital inputs/outputs
_DIO digitalInOut;
digitalInOut.dio1_enable = false;
digitalInOut.dio2_enable = false;
digitalInOut.dio3_enable = false;
digitalInOut.dio4_enable = false;
digitalInOut.dio5_enable = false;
digitalInOut.dio6_enable = false;
digitalInOut.dio7_enable = false;
digitalInOut.dio8_enable = false;
// channel initialisation
if (!m_gTec->m_fInitChannels(m_gTec->m_device, m_gTec->m_analogIn, digitalInOut))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "GT_InitChannels failed\n";
return false;
}
// are we interested in test signal?
m_gTec->m_fSetTestmode(m_gTec->m_device, m_testMode);
// requests hardware to start sending data
if (!m_gTec->m_fStartAcquisition(m_gTec->m_device))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "GT_StartAcquisition failed\n";
return false;
}
return true;
}
bool CDriverGTecGMobiLabPlus::loop()
{
// m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::loop\n";
if (!m_driverCtx.isConnected() || !m_driverCtx.isStarted()) { return true; }
const size_t nChannel = m_header->getChannelCount();
// only "l-nChannel" measures corresponding to one measure per channel are acquired in a row with the function GT_GetData()
// these measures are stored in m_oBuffer.pBuffer[]
// the acquisition is reapeted m_sampleCountPerSendBlock times to fill in the array "m_sample"
for (uint32_t i = 0; i < m_nSamplePerSentBlock; ++i)
{
#if defined(TARGET_OS_Windows)
if (!m_gTec->m_fGetData(m_gTec->m_device, &m_gTec->m_oBuffer, &m_gTec->m_oOverlap))// receive samples from hardware (one per channel)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "GT_GetData failed\n";
return false;
}
if (WaitForSingleObject(m_gTec->m_oOverlap.hEvent, 1000) == WAIT_TIMEOUT)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Warning << "Timeout in reading from the device\n";
return false;
}
#else
if (!m_gTec->m_fGetData(m_gTec->m_device, &m_gTec->m_oBuffer))// receive samples from hardware (one per channel)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "GT_GetData failed\n";
return false;
}
#endif
// here the "nChannel" measures just acquired are stored in m_sample not to be deleted by the next acquisition
// m_driverCtx.getLogManager() << Kernel::LogLevel_Debug << "Here are the " << nChannel << " measures of the " << i << " th sample\n" << Kernel::LogLevel_Debug;
for (uint32_t j = 0; j < nChannel; ++j)
{
// m_driverCtx.getLogManager() << (m_oBuffer.pBuffer[j]*0.5)/32768. << " ";
//operation made to modify the short int in a number between 0 and 500mV (in Volt)
m_sample[m_nSamplePerSentBlock * j + i] = float((m_gTec->m_oBuffer.pBuffer[j] * 0.5) / 32768.);
}
// m_driverCtx.getLogManager() << "\n";
}
// the buffer is full : it is send to the acquisition server
m_callback->setSamples(m_sample, m_nSamplePerSentBlock);
m_driverCtx.correctDriftSampleCount(m_driverCtx.getSuggestedDriftCorrectionSampleCount());
return true;
}
bool CDriverGTecGMobiLabPlus::stop()
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "CDriverGTecGMobiLabPlus::stop\n";
if (!m_driverCtx.isConnected() || !m_driverCtx.isStarted()) { return false; }
// requests the hardware to stop sending data
if (!m_gTec->m_fStopAcquisition(m_gTec->m_device))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "GT_StopAcquisition failed\n";
return false;
}
return true;
}
// this function allows exchanges of data on the "index" channel
// function used to initialize the analog inputs according to the number "nChannel"
void CDriverGTecGMobiLabPlus::allowAnalogInputs(uint32_t index)
{
switch (index)
{
case 8: m_gTec->m_analogIn.ain8 = true;
break;
case 7: m_gTec->m_analogIn.ain7 = true;
break;
case 6: m_gTec->m_analogIn.ain6 = true;
break;
case 5: m_gTec->m_analogIn.ain5 = true;
break;
case 4: m_gTec->m_analogIn.ain4 = true;
break;
case 3: m_gTec->m_analogIn.ain3 = true;
break;
case 2: m_gTec->m_analogIn.ain2 = true;
break;
case 1: m_gTec->m_analogIn.ain1 = true;
break;
default: m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Unexpected value " << index << " in CDriverGTecGMobiLabPlus::allowAnalogInputs\n";
break;
}
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGMobiLabPlusAPI
@@ -0,0 +1,86 @@
/**
* The gMobilab driver was contributed
* by Lucie Daubigney from Supelec Metz
*/
#pragma once
#if defined TARGET_HAS_ThirdPartyGMobiLabPlusAPI
#include "ovasIDriver.h"
#include "../ovasCHeader.h"
#include "../ovasCSettingsHelper.h"
#include "../ovasCSettingsHelperOperators.h"
#include <string>
#ifdef TARGET_OS_Windows
#include <Windows.h>
#endif
namespace OpenViBE {
namespace AcquisitionServer {
class CDriverGTecGMobiLabPlusPrivate; // fwd declare
/**
* \class CDriverGTecGMobiLabPlus
* \author Lucie Daubigney (Supelec Metz)
*/
class CDriverGTecGMobiLabPlus final : public IDriver
{
public:
explicit CDriverGTecGMobiLabPlus(IDriverContext& ctx);
~CDriverGTecGMobiLabPlus() override;
void release();
const char* getName() override;
bool isFlagSet(const EDriverFlag flag) const override { return flag == EDriverFlag::IsUnstable; }
//configuration
bool isConfigurable() override;
bool configure() override;
//initialisation
bool initialize(const uint32_t sampleCountPerChannel, IDriverCallback& callback) override;
bool uninitialize() override;
const IHeader* getHeader() override;
//acquisition
bool start() override;
bool stop() override;
bool loop() override;
protected:
SettingsHelper m_settings;
//usefull data to communicate with OpenViBE
IHeader* m_header = nullptr;
IDriverCallback* m_callback = nullptr;
uint32_t m_nSamplePerSentBlock = 0;//number of sample you want to send in a row
float* m_sample = nullptr;//array containing the data to sent to OpenViBE once they had been recovered from the gTec module
//params
std::string m_portName;
bool m_testMode = false;
// Pointers do gtec-specific data and function pointers
CDriverGTecGMobiLabPlusPrivate* m_gTec = nullptr;
// Register the function pointers from the dll. (The dll approach
// is used with gMobilab to avoid conflicts with the gUSBAmp lib)
bool registerLibraryFunctions();
#if defined(TARGET_OS_Windows)
HINSTANCE m_library;
#elif defined(TARGET_OS_Linux)
void* m_library = nullptr;
#endif
private:
void allowAnalogInputs(uint32_t index);
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGMobiLabPlusAPI
@@ -0,0 +1,85 @@
/*
* The only purpose of this class is to hide the gtec API
* data types from the ov driver header. An approach resembling
* this is sometimes called a 'd-pointer'.
*
* Previous situation:
*
* gUsbamp ov driver header depends on gtec gUSBAmp API types
* gMobilab ov driver header depends on gtec gMobilab API types
* Acquisition Server includes both these driver headers
*
* But the gtec types are declared differently in the two gtec APIs.
* Hence we get a conflict if both headers are included by the
* same compilation unit.
*
* With this class, the gmobilab API is not exposed just by
* including ovasCDriverGtecMobiLabPlus.h to the Acquisition Server.
*
*/
#pragma once
#if defined TARGET_HAS_ThirdPartyGMobiLabPlusAPI
#include <gMOBIlabplus.h>
namespace OpenViBE {
namespace AcquisitionServer {
/**
* \author Jussi T. Lindgren (Inria)
*
* The class collects all members that used to be in
* CDriverGtecMobiLabPlus header that depend on the gmobilab API.
*
*/
class CDriverGTecGMobiLabPlusPrivate
{
public:
//useful data to communicate with the gTec module
_BUFFER_ST m_oBuffer;
HANDLE m_device;
_AIN m_analogIn;
#if defined(TARGET_OS_Windows)
OVERLAPPED m_oOverlap;
#endif
// These functions are defined in the gmobilab library
#if defined(TARGET_OS_Windows)
typedef HANDLE (__stdcall *OV_GT_OpenDevice)(LPSTR lpPort);
typedef BOOL (__stdcall *OV_GT_CloseDevice)(HANDLE hDevice);
typedef BOOL (__stdcall *OV_GT_SetTestmode)(HANDLE hDevice, BOOL Testmode);
typedef BOOL (__stdcall *OV_GT_StartAcquisition)(HANDLE hDevice);
typedef BOOL (__stdcall *OV_GT_GetData)(HANDLE hDevice, _BUFFER_ST* buffer, LPOVERLAPPED lpOvl);
typedef BOOL (__stdcall *OV_GT_InitChannels)(HANDLE hDevice, _AIN analogCh, _DIO digitalCh);
typedef bool (__stdcall *OV_GT_StopAcquisition)(HANDLE hDevice);
typedef bool (__stdcall *OV_GT_GetLastError)(UINT* LastError);
typedef bool (__stdcall *OV_GT_TranslateErrorCode)(_ERRSTR* ErrorString, UINT ErrorCode);
#else
typedef HANDLE(*OV_GT_OpenDevice)(const char* lpPort);
typedef bool(*OV_GT_CloseDevice)(HANDLE hDevice);
typedef bool(*OV_GT_SetTestmode)(HANDLE hDevice, bool Testmode);
typedef bool(*OV_GT_StartAcquisition)(HANDLE hDevice);
typedef bool(*OV_GT_GetData)(HANDLE hDevice, _BUFFER_ST *buffer);
typedef bool(*OV_GT_InitChannels)(HANDLE hDevice, _AIN analogCh, _DIO digitalCh);
typedef bool(*OV_GT_StopAcquisition)(HANDLE hDevice);
typedef bool(*OV_GT_GetLastError)(uint32_t* LastError);
typedef bool(*OV_GT_TranslateErrorCode)(_ERRSTR *ErrorString, uint32_t ErrorCode);
#endif
// Function pointers to the dll
OV_GT_OpenDevice m_fOpenDevice;
OV_GT_CloseDevice m_fCloseDevice;
OV_GT_SetTestmode m_fSetTestmode;
OV_GT_StartAcquisition m_fStartAcquisition;
OV_GT_GetData m_fGetData;
OV_GT_InitChannels m_fInitChannels;
OV_GT_StopAcquisition m_fStopAcquisition;
OV_GT_GetLastError m_fGetLastError;
OV_GT_TranslateErrorCode m_fTranslateErrorCode;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGMobiLabPlusAPI