init
This commit is contained in:
+432
@@ -0,0 +1,432 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.6 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="upper">100</property>
|
||||
<property name="value">18</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="lower">1</property>
|
||||
<property name="upper">128</property>
|
||||
<property name="value">128</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment4">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">254</property>
|
||||
<property name="value">1</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">300</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">500</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">540</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">600</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">1000</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkDialog" id="openvibe-acquisition-server-settings">
|
||||
<property name="can_focus">False</property>
|
||||
<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>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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 internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Cognionics</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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="can_focus">False</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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="GtkSpinButton" id="spinbutton_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</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">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="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">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>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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">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="can_focus">False</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">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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="GtkLabel" id="label_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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_identifier">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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="GtkComboBox" id="combobox_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">model2</property>
|
||||
<property name="active">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">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">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>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0.49000000953674316</property>
|
||||
<property name="label" translatable="yes">COM Port:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_comport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment4</property>
|
||||
</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="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Check impedance :</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_impedance">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<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">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</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>
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
#if defined(WIN32)
|
||||
|
||||
#include "ovasCConfigurationCognionics.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
|
||||
/*_________________________________________________
|
||||
|
||||
Insert callback to specific widget here
|
||||
Example with a button that launch a calibration of the device:
|
||||
|
||||
//Callback connected to a dedicated gtk button:
|
||||
static void button_calibrate_pressed_cb(GtkButton* button, void* data)
|
||||
{
|
||||
CConfigurationCognionics* config=static_cast<CConfigurationCognionics*>(data);
|
||||
config->buttonCalibratePressedCB();
|
||||
}
|
||||
|
||||
//Callback actually called:
|
||||
void CConfigurationGTecGUSBamp::buttonCalibratePressedCB()
|
||||
{
|
||||
// Connect to the hardware, ask for calibration, verify the return code, etc.
|
||||
}
|
||||
_________________________________________________*/
|
||||
|
||||
// If you added more reference attribute, initialize them here
|
||||
CConfigurationCognionics::CConfigurationCognionics(IDriverContext& ctx, const char* gtkBuilderFilename, uint32_t& comport)
|
||||
: CConfigurationBuilder(gtkBuilderFilename), m_COMPORT(comport), m_driverCtx(ctx) {}
|
||||
|
||||
bool CConfigurationCognionics::preConfigure()
|
||||
{
|
||||
if (! CConfigurationBuilder::preConfigure()) { return false; }
|
||||
|
||||
GtkSpinButton* comport = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder, "spinbutton_comport"));
|
||||
|
||||
gtk_spin_button_set_value(comport, m_COMPORT);
|
||||
|
||||
// Connect here all callbacks
|
||||
// Example:
|
||||
// g_signal_connect(gtk_builder_get_object(m_builder, "button_calibrate"), "pressed", G_CALLBACK(button_calibrate_pressed_cb), this);
|
||||
|
||||
// Insert here the pre-configure code.
|
||||
// For example, you may want to check if a device is currently connected
|
||||
// and if more than one are connected. Then you can list in a dedicated combo-box
|
||||
// the device currently connected so the user can choose which one he wants to acquire from.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfigurationCognionics::postConfigure()
|
||||
{
|
||||
if (m_applyConfig)
|
||||
{
|
||||
GtkSpinButton* comport = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder, "spinbutton_comport"));
|
||||
|
||||
m_COMPORT = uint32_t(gtk_spin_button_get_value(comport));
|
||||
//printf("Selected COM Port: %d", m_COMPORT);
|
||||
// If the user pressed the "apply" button, you need to save the changes made in the configuration.
|
||||
// For example, you can save the connection ID of the selected device:
|
||||
// m_connectionID = <value-from-gtk-widget>
|
||||
}
|
||||
|
||||
if (! CConfigurationBuilder::postConfigure()
|
||||
) { return false; } // normal header is filled (Subject ID, Age, Gender, channels, sampling frequency), ressources are realesed
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
#endif // WIN32
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovasCConfigurationBuilder.h"
|
||||
#include "ovasIDriver.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
/**
|
||||
* \class CConfigurationCognionics
|
||||
* \author Mike Chi (Cognionics, Inc.)
|
||||
* \copyright AGPL3
|
||||
* \date Thu Apr 18 21:19:49 2013
|
||||
* \brief The CConfigurationCognionics handles the configuration dialog specific to the Cognionics device.
|
||||
*
|
||||
* TODO: details
|
||||
*
|
||||
* \sa CDriverCognionics
|
||||
*/
|
||||
class CConfigurationCognionics final : public CConfigurationBuilder
|
||||
{
|
||||
public:
|
||||
// you may have to add to your constructor some reference parameters
|
||||
// for example, a connection ID:
|
||||
//CConfigurationCognionics(IDriverContext& ctx, const char* gtkBuilderFilename, uint32_t& rConnectionId);
|
||||
CConfigurationCognionics(IDriverContext& ctx, const char* gtkBuilderFilename, uint32_t& comport);
|
||||
|
||||
bool preConfigure() override;
|
||||
bool postConfigure() override;
|
||||
|
||||
uint32_t& m_COMPORT;
|
||||
|
||||
|
||||
protected:
|
||||
IDriverContext& m_driverCtx;
|
||||
|
||||
/*
|
||||
* Insert here all specific attributes, such as a connection ID.
|
||||
* use references to directly modify the corresponding attribute of the driver
|
||||
* Example:
|
||||
*/
|
||||
};
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
+398
@@ -0,0 +1,398 @@
|
||||
#include "ovasCDriverCognionics.h"
|
||||
#include "ovasCConfigurationCognionics.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
|
||||
//Cognionics functions
|
||||
|
||||
int init_SPP(int port);
|
||||
void getData();
|
||||
double get_IMP_CH(int ch);
|
||||
void close_SPP();
|
||||
unsigned long grab_SPP(int bytes, unsigned char* buf);
|
||||
void write_SPP(int bytes, unsigned char* buf);
|
||||
|
||||
//Cognionics defs
|
||||
#define GAIN 3.0
|
||||
#define VREF 2.5
|
||||
#define ISTIM 0.000000024
|
||||
#define ADC_TO_VOLTS 2.0*(VREF/(4294967296.0*GAIN))
|
||||
#define TO_Z 1.4/(ISTIM*2.0)
|
||||
|
||||
//Cognionics variables
|
||||
int EEG_GRAB;
|
||||
int CHS;
|
||||
int SAMPLE_RATE;
|
||||
float* dataBufferPtr;
|
||||
int prev_trigger;
|
||||
CStimulationSet cogStimulationSet;
|
||||
|
||||
//Cognionics Buffers
|
||||
int* prev_4_samples; //buffer for previous 4 samples in each channel for computing MA and IMP
|
||||
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
|
||||
CDriverCognionics::CDriverCognionics(IDriverContext& ctx)
|
||||
: IDriver(ctx), m_settings("AcquisitionServer_Driver_Cognionics", m_driverCtx.getConfigurationManager()), m_comPort(1)
|
||||
{
|
||||
m_header.setSamplingFrequency(300);
|
||||
m_header.setChannelCount(64);
|
||||
|
||||
m_settings.add("Header", &m_header);
|
||||
m_settings.add("ComPort", &m_comPort);
|
||||
m_settings.load();
|
||||
}
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
|
||||
bool CDriverCognionics::initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback)
|
||||
{
|
||||
if (m_driverCtx.isConnected() || !m_header.isChannelCountSet() || !m_header.isSamplingFrequencySet()) { return false; }
|
||||
|
||||
// Builds up a buffer to store
|
||||
// acquired samples. This buffer
|
||||
// will be sent to the acquisition
|
||||
// server later...
|
||||
m_sample = new float[m_header.getChannelCount() * nSamplePerSentBlock];
|
||||
|
||||
//initalize Cognionics varaibles, pointers and buffers
|
||||
EEG_GRAB = nSamplePerSentBlock;
|
||||
SAMPLE_RATE = m_header.getSamplingFrequency();
|
||||
CHS = m_header.getChannelCount();
|
||||
dataBufferPtr = &m_sample[0];
|
||||
prev_4_samples = new int[EEG_GRAB * CHS];
|
||||
|
||||
if (!m_sample)
|
||||
{
|
||||
delete [] m_sample;
|
||||
delete [] prev_4_samples;
|
||||
m_sample = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...
|
||||
// initialize hardware and get
|
||||
// available header information
|
||||
// from it
|
||||
// Using for example the connection ID provided by the configuration (m_connectionID)
|
||||
// ...
|
||||
|
||||
//init serial port
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Attempting to Connect to Device at COM Port: " << m_comPort << "\n";
|
||||
|
||||
const int serSuccess = init_SPP(m_comPort);
|
||||
if (serSuccess == -1)
|
||||
{
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Unable to Open Port, Please Check Device and Settings\n";
|
||||
return false;
|
||||
}
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Successfully Opened Port at COM: " << m_comPort << "\n";
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Number Channels (EEG + Packet Counter + Trigger): " << m_header.getChannelCount() << "\n";
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Sampling Rate: " << m_header.getSamplingFrequency() << "\n";
|
||||
|
||||
for (size_t c = 0; c < m_header.getChannelCount(); ++c) { m_header.setChannelUnits(c, OVTK_UNIT_Volts, OVTK_FACTOR_Base); }
|
||||
|
||||
//set impedance check mode ON
|
||||
getData();
|
||||
unsigned char imp_on = 0x11;
|
||||
write_SPP(1, &imp_on);
|
||||
|
||||
// Saves parameters
|
||||
m_callback = &callback;
|
||||
m_nSamplePerSentBlock = nSamplePerSentBlock;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverCognionics::start()
|
||||
{
|
||||
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
// ...
|
||||
// request hardware to start
|
||||
// sending data
|
||||
// ...
|
||||
|
||||
//set impedance check mode off
|
||||
getData();
|
||||
unsigned char imp_off = 0x12;
|
||||
write_SPP(1, &imp_off);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverCognionics::loop()
|
||||
{
|
||||
if (!m_driverCtx.isConnected()) { return false; }
|
||||
|
||||
if (m_driverCtx.isStarted())
|
||||
{
|
||||
// ...
|
||||
// receive samples from hardware
|
||||
// put them the correct way in the sample array
|
||||
// whether the buffer is full, send it to the acquisition server
|
||||
//...
|
||||
|
||||
//get the number of samples specified
|
||||
getData();
|
||||
|
||||
//OpenVibe call back for new samples
|
||||
m_callback->setSamples(m_sample);
|
||||
|
||||
// When your sample buffer is fully loaded,
|
||||
// it is advised to ask the acquisition server
|
||||
// to correct any drift in the acquisition automatically.
|
||||
m_driverCtx.correctDriftSampleCount(m_driverCtx.getSuggestedDriftCorrectionSampleCount());
|
||||
|
||||
// ...
|
||||
// receive events from hardware
|
||||
// and put them the correct way in a CStimulationSet object
|
||||
//...
|
||||
m_callback->setStimulationSet(cogStimulationSet);
|
||||
cogStimulationSet.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
//get a fresh batch of samples to keep connection alive
|
||||
getData();
|
||||
if (m_driverCtx.isImpedanceCheckRequested())
|
||||
{
|
||||
//update impedance values
|
||||
for (int c = 0; c < CHS; ++c) { m_driverCtx.updateImpedance(c, get_IMP_CH(c)); }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverCognionics::stop()
|
||||
{
|
||||
if (!m_driverCtx.isConnected() || !m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
// ...
|
||||
// request the hardware to stop
|
||||
// sending data
|
||||
// ...
|
||||
|
||||
//set impedance check mode on
|
||||
getData();
|
||||
unsigned char imp_off = 0x11;
|
||||
write_SPP(1, &imp_off);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverCognionics::uninitialize()
|
||||
{
|
||||
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
// ...
|
||||
// uninitialize hardware here
|
||||
// ...
|
||||
close_SPP();
|
||||
|
||||
//free buffers
|
||||
delete [] m_sample;
|
||||
delete [] prev_4_samples;
|
||||
m_sample = nullptr;
|
||||
m_callback = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
bool CDriverCognionics::isConfigurable()
|
||||
{
|
||||
return true; // change to false if your device is not configurable
|
||||
}
|
||||
|
||||
bool CDriverCognionics::configure()
|
||||
{
|
||||
// Change this line if you need to specify some references to your driver attribute that need configuration, e.g. the connection ID.
|
||||
CConfigurationCognionics config(m_driverCtx,
|
||||
Directories::getDataDir() + "/applications/acquisition-server/interface-Cognionics.ui",
|
||||
m_comPort); // the specific header is passed into the specific configuration
|
||||
|
||||
if (!config.configure(m_header)) { return false; }
|
||||
|
||||
m_settings.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void getData()
|
||||
{
|
||||
unsigned char packet_start = 0;
|
||||
int lsb2, lsb1;
|
||||
unsigned char temp;
|
||||
|
||||
for (int c = 0; c < EEG_GRAB; ++c)
|
||||
{
|
||||
packet_start = 0;
|
||||
|
||||
//wait for packet start
|
||||
while (packet_start != 0xFF) { grab_SPP(1, &packet_start); }
|
||||
|
||||
//get packet counter
|
||||
grab_SPP(1, &packet_start);
|
||||
|
||||
//grab CHS-2 since the last two channels are for sync and packet counter
|
||||
for (int j = 0; j < (CHS - 2); ++j)
|
||||
{
|
||||
grab_SPP(1, &temp);
|
||||
int msb = temp;
|
||||
grab_SPP(1, &temp);
|
||||
lsb2 = temp;
|
||||
grab_SPP(1, &temp);
|
||||
lsb1 = temp;
|
||||
|
||||
//reassemble 24-bit 2's compltement promoted to 32 bit int
|
||||
msb = (msb << 24) | (lsb2 << 17) | (lsb1 << 10);
|
||||
|
||||
//shift previous 4 sample buffer
|
||||
*(prev_4_samples + j * 4 + 3) = *(prev_4_samples + j * 4 + 2);
|
||||
*(prev_4_samples + j * 4 + 2) = *(prev_4_samples + j * 4 + 1);
|
||||
*(prev_4_samples + j * 4 + 1) = *(prev_4_samples + j * 4 + 0);
|
||||
*(prev_4_samples + j * 4 + 0) = msb;
|
||||
|
||||
const double sample = ADC_TO_VOLTS * double(msb);
|
||||
|
||||
//4-point MA for devices without way to disable impedance
|
||||
/*
|
||||
eeg_sample = ADC_TO_VOLTS * ((double) *(prev_4_samples + j*4 + 3) +
|
||||
*(prev_4_samples + j*4 + 2) +
|
||||
*(prev_4_samples + j*4 + 1) +
|
||||
*(prev_4_samples + j*4 + 0) )/4.0;
|
||||
*/
|
||||
|
||||
*(dataBufferPtr + j * EEG_GRAB + c) = float(sample);
|
||||
}
|
||||
|
||||
|
||||
//save packet counter;
|
||||
*(dataBufferPtr + (CHS - 1) * EEG_GRAB + c) = float(packet_start);
|
||||
|
||||
//dummy data
|
||||
grab_SPP(1, &temp);
|
||||
grab_SPP(1, &temp);
|
||||
|
||||
//grab trigger
|
||||
grab_SPP(1, &temp);
|
||||
lsb2 = temp;
|
||||
grab_SPP(1, &temp);
|
||||
lsb1 = temp;
|
||||
|
||||
//assemble trigger code
|
||||
int newTrigger = (lsb2 << 8) | lsb1;
|
||||
//downshift serial triggers if necessary
|
||||
if (newTrigger > 255) { newTrigger = newTrigger >> 8; }
|
||||
|
||||
//store in EEG channel
|
||||
*(dataBufferPtr + (CHS - 2) * EEG_GRAB + c) = float(newTrigger);
|
||||
|
||||
//detect new stimulation
|
||||
if (newTrigger != prev_trigger)
|
||||
{
|
||||
//time offset from start of chunk (c - current sample in the chunk)
|
||||
const uint64_t date = c * (1LL << 32) / SAMPLE_RATE;
|
||||
cogStimulationSet.appendStimulation(OVTK_StimulationId_Label(newTrigger&0x000000ff), date, 0);
|
||||
}
|
||||
|
||||
prev_trigger = newTrigger;
|
||||
}
|
||||
}
|
||||
|
||||
double get_IMP_CH(const int ch)
|
||||
{
|
||||
double d1 = double(*(prev_4_samples + ch * 4 + 2)) - double(*(prev_4_samples + ch * 4 + 0));
|
||||
double d2 = double(*(prev_4_samples + ch * 4 + 3)) - double(*(prev_4_samples + ch * 4 + 1));
|
||||
d1 = d1 * ADC_TO_VOLTS;
|
||||
d2 = d2 * ADC_TO_VOLTS;
|
||||
|
||||
if (d1 < 0) { d1 = -d1; }
|
||||
if (d2 < 0) { d2 = -d2; }
|
||||
|
||||
if (d2 > d1) { d1 = d2; }
|
||||
|
||||
return d1 * TO_Z;
|
||||
}
|
||||
|
||||
//serial port handling
|
||||
|
||||
HANDLE hSerial;
|
||||
COMMTIMEOUTS timeouts = { 0 };
|
||||
|
||||
int init_SPP(const int port)
|
||||
{
|
||||
char com[100];
|
||||
|
||||
sprintf(com, "\\\\.\\COM%d", port);
|
||||
|
||||
hSerial = CreateFile(com, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
if (hSerial == INVALID_HANDLE_VALUE) { return -1; }
|
||||
|
||||
//setup serial port parameters
|
||||
DCB dcbSerialParams = { 0 };
|
||||
|
||||
if (!GetCommState(hSerial, &dcbSerialParams))
|
||||
{
|
||||
//error getting state
|
||||
}
|
||||
|
||||
dcbSerialParams.BaudRate = 1500000;
|
||||
dcbSerialParams.ByteSize = 8;
|
||||
dcbSerialParams.StopBits = ONESTOPBIT;
|
||||
dcbSerialParams.Parity = NOPARITY;
|
||||
|
||||
if (!SetCommState(hSerial, &dcbSerialParams))
|
||||
{
|
||||
//error setting serial port state
|
||||
}
|
||||
|
||||
//setup serial port timeout
|
||||
COMMTIMEOUTS timeouts;
|
||||
timeouts.ReadIntervalTimeout = 500;
|
||||
timeouts.ReadTotalTimeoutConstant = 50;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||
|
||||
timeouts.WriteTotalTimeoutConstant = 50;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||
if (!SetCommTimeouts(hSerial, &timeouts))
|
||||
{
|
||||
//error occureed. Inform user
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_SPP() { CloseHandle(hSerial); }
|
||||
|
||||
unsigned long grab_SPP(const int bytes, unsigned char* buf)
|
||||
{
|
||||
DWORD dwBytesRead = 0;
|
||||
ReadFile(hSerial, buf, bytes, &dwBytesRead, nullptr);
|
||||
|
||||
return int(dwBytesRead);
|
||||
}
|
||||
|
||||
void write_SPP(const int bytes, unsigned char* buf)
|
||||
{
|
||||
DWORD dwBytesWritten = 0;
|
||||
WriteFile(hSerial, buf, bytes, &dwBytesWritten, nullptr);
|
||||
}
|
||||
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
#endif //WIN32
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovasIDriver.h"
|
||||
#include "../ovasCHeader.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
|
||||
#include "../ovasCSettingsHelper.h"
|
||||
#include "../ovasCSettingsHelperOperators.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
/**
|
||||
* \class CDriverCognionics
|
||||
* \author Mike Chi (Cognionics, Inc.)
|
||||
* \copyright AGPL3
|
||||
* \date Thu Apr 18 21:19:49 2013
|
||||
|
||||
* \brief The CDriverCognionics allows the acquisition server to acquire data from a Cognionics device.
|
||||
*
|
||||
* TODO: details
|
||||
*
|
||||
* \sa CConfigurationCognionics
|
||||
*/
|
||||
class CDriverCognionics final : public IDriver
|
||||
{
|
||||
public:
|
||||
|
||||
explicit CDriverCognionics(IDriverContext& ctx);
|
||||
~CDriverCognionics() override {}
|
||||
const char* getName() override { return "Cognionics"; }
|
||||
|
||||
bool initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback) override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool start() override;
|
||||
bool stop() override;
|
||||
bool loop() override;
|
||||
|
||||
bool isConfigurable() override;
|
||||
bool configure() override;
|
||||
const IHeader* getHeader() override { return &m_header; }
|
||||
|
||||
bool isFlagSet(const EDriverFlag flag) const override { return flag == EDriverFlag::IsUnstable; }
|
||||
|
||||
protected:
|
||||
|
||||
SettingsHelper m_settings;
|
||||
IDriverCallback* m_callback = nullptr;
|
||||
|
||||
// Replace this generic Header with any specific header you might have written
|
||||
CHeader m_header;
|
||||
uint32_t m_nSamplePerSentBlock = 0;
|
||||
float* m_sample = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Insert here all specific attributes, such as USB port number or device ID.
|
||||
* Example :
|
||||
*/
|
||||
uint32_t m_comPort = 0;
|
||||
};
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
Reference in New Issue
Block a user