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,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>
@@ -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
@@ -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
@@ -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
@@ -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