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,768 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- 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">1024</property>
<property name="value">4</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkWindow" id="dummy_window">
<property name="can_focus">False</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">8</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<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">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_sampling_frequency">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_sampling_frequency</property>
<child>
<object class="GtkCellRendererText" id="renderer_sampling_frequency"/>
<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>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="label_type">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Device type :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label_number_of_channels">
<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">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_type">
<property name="can_focus">False</property>
<property name="model">model_type</property>
<child>
<object class="GtkCellRendererText" id="renderer_type"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">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">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkListStore" id="model_baud_rate">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">default</col>
</row>
<row>
<col id="0" translatable="yes">9 600</col>
</row>
<row>
<col id="0" translatable="yes">115 200</col>
</row>
<row>
<col id="0" translatable="yes">460 800</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_bit_depth">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">default</col>
</row>
<row>
<col id="0" translatable="yes">8 bits</col>
</row>
<row>
<col id="0" translatable="yes">16 bits</col>
</row>
<row>
<col id="0" translatable="yes">24 bits</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_gender">
<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="model_notch_filters">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">default</col>
</row>
<row>
<col id="0" translatable="yes">none</col>
</row>
<row>
<col id="0" translatable="yes">50Hz</col>
</row>
<row>
<col id="0" translatable="yes">60Hz</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_preset">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Custom</col>
</row>
<row>
<col id="0" translatable="yes">Discovery 24</col>
</row>
<row>
<col id="0" translatable="yes">Atlantis 4x4</col>
</row>
<row>
<col id="0" translatable="yes">Atlantis 2x2</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_sampling_frequency">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">256</col>
</row>
<row>
<col id="0" translatable="yes">512</col>
</row>
<row>
<col id="0" translatable="yes">1024</col>
</row>
<row>
<col id="0" translatable="yes">2048</col>
</row>
</data>
</object>
<object class="GtkListStore" id="model_type">
<columns>
<!-- column-name text -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Discovery</col>
</row>
<row>
<col id="0" translatable="yes">Atlantis</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_action_appearance">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_action_appearance">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">Brainmaster Discovery / Atlantis
&lt;small&gt;&lt;span color="darkred"&gt;Attention : You should obtain a device passkey from Brainmaster
in order to operate your device with OpenViBE&lt;/span&gt;&lt;/small&gt;</property>
<property name="use_markup">True</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="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">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="GtkTable" id="table2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">12</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<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">4</property>
<property name="bottom_attach">5</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">3</property>
<property name="bottom_attach">4</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>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_gender">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_gender</property>
<child>
<object class="GtkCellRendererText" id="renderer_gender"/>
<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_age">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">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">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spinbutton_identifier">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">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>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator3">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_device_preset">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Configuration preset :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
</child>
<child>
<object class="GtkComboBox" id="combobox_device_preset">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_preset</property>
<child>
<object class="GtkCellRendererText" id="renderer_device_preset"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_device">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Device port :</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>
<child>
<object class="GtkComboBox" id="combobox_device">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkCellRendererText" id="renderer_device"/>
<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_baud_rate">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Baud rate :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_bit_depth">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Bit depth :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_notch_filters">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Notch filter :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">8</property>
<property name="bottom_attach">9</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_baud_rate">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_baud_rate</property>
<child>
<object class="GtkCellRendererText" id="renderer_baud_rate"/>
<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">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_bit_depth">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_bit_depth</property>
<child>
<object class="GtkCellRendererText" id="renderer_bit_depth"/>
<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">7</property>
<property name="bottom_attach">8</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combobox_notch_filters">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model_notch_filters</property>
<child>
<object class="GtkCellRendererText" id="renderer_notch_filters"/>
<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">8</property>
<property name="bottom_attach">9</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator2">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="right_attach">2</property>
<property name="top_attach">9</property>
<property name="bottom_attach">10</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_device_serial">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Device Serial Nr :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">10</property>
<property name="bottom_attach">11</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_device_passkey">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Device Passkey :</property>
<property name="justify">right</property>
<property name="single_line_mode">True</property>
</object>
<packing>
<property name="top_attach">11</property>
<property name="bottom_attach">12</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_device_serial">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">10</property>
<property name="bottom_attach">11</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_device_passkey">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">11</property>
<property name="bottom_attach">12</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">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">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="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">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,317 @@
/*
* ovasCConfigurationBrainmasterDiscovery.cpp
*
* Copyright (c) 2012, Yann Renard. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#if defined TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
#include "ovasCConfigurationBrainmasterDiscovery.h"
#include "ovas_defines_brainmaster_discovery.h"
namespace OpenViBE {
namespace AcquisitionServer {
namespace {
static bool guardFlag = false;
void on_spin_button_changed(GtkSpinButton* pAnySpinButton, GtkComboBox* pDevicePresetComboBox)
{
if (!guardFlag) { gtk_combo_box_set_active(pDevicePresetComboBox, 0); } // Custom
}
void on_combo_box_changed(GtkComboBox* pAnyComboBox, GtkComboBox* pDevicePresetComboBox)
{
if (!guardFlag) { gtk_combo_box_set_active(pDevicePresetComboBox, 0); } // Custom
}
void on_device_preset_changed(GtkComboBox* pComboBox, CConfigurationBrainmasterDiscovery* pThis)
{
guardFlag = true;
// int i;
const int active = gtk_combo_box_get_active(pComboBox);
switch (active)
{
default:
case Preset_Custom: break;
case Preset_Discovery_24: gtk_spin_button_set_value(pThis->m_buttonChannelCount, 24); // 22 EEG channels + 2 AUX
gtk_combo_box_set_active(pThis->m_comboBoxType, 0); // Discovery
gtk_combo_box_set_active(pThis->m_comboBoxSamplingRate, 0); // default
//gtk_combo_box_set_active(pThis->m_comboBoxDevice, );
//gtk_combo_box_set_active(pThis->m_comboBoxPreset, );
gtk_combo_box_set_active(pThis->m_comboBoxBaudRate, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxBitDepth, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxNotchFilters, 0); // default
gtk_widget_set_sensitive(GTK_WIDGET(pThis->m_comboBoxBitDepth), FALSE); // default
pThis->m_rvChannelType.clear();
//for (i=0; i<22; ++i) pThis->m_rvChannelType[i]=ChannelType_EEG;
//for (i=22; i<24; ++i) pThis->m_rvChannelType[i]=ChannelType_AUX;
pThis->m_channelNames[0] = "Fp1";
pThis->m_channelNames[1] = "F3";
pThis->m_channelNames[2] = "C3";
pThis->m_channelNames[3] = "P3";
pThis->m_channelNames[4] = "O1";
pThis->m_channelNames[5] = "F7";
pThis->m_channelNames[6] = "T3";
pThis->m_channelNames[7] = "T5";
pThis->m_channelNames[8] = "Fz";
pThis->m_channelNames[9] = "Fp2";
pThis->m_channelNames[10] = "F4";
pThis->m_channelNames[11] = "C4";
pThis->m_channelNames[12] = "P4";
pThis->m_channelNames[13] = "O2";
pThis->m_channelNames[14] = "F8";
pThis->m_channelNames[15] = "T4";
pThis->m_channelNames[16] = "T6";
pThis->m_channelNames[17] = "Cz";
pThis->m_channelNames[18] = "Pz";
pThis->m_channelNames[19] = "A2";
pThis->m_channelNames[20] = "Fpz";
pThis->m_channelNames[21] = "Oz";
pThis->m_channelNames[22] = "AUX1";
pThis->m_channelNames[23] = "AUX2";
break;
case Preset_Atlantis_2x2: gtk_spin_button_set_value(pThis->m_buttonChannelCount, 4); // 2 EEG channels + 2 AUX
gtk_combo_box_set_active(pThis->m_comboBoxType, 1); // Atlantis
gtk_combo_box_set_active(pThis->m_comboBoxSamplingRate, 0); // default
//gtk_combo_box_set_active(pThis->m_comboBoxDevice, );
//gtk_combo_box_set_active(pThis->m_comboBoxPreset, );
gtk_combo_box_set_active(pThis->m_comboBoxBaudRate, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxBitDepth, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxNotchFilters, 0); // default
gtk_widget_set_sensitive(GTK_WIDGET(pThis->m_comboBoxBitDepth), TRUE); // default
pThis->m_rvChannelType.clear();
pThis->m_rvChannelType[0] = ChannelType_AUX;
pThis->m_rvChannelType[1] = ChannelType_AUX;
pThis->m_rvChannelType[2] = ChannelType_EEG;
pThis->m_rvChannelType[3] = ChannelType_EEG;
pThis->m_channelNames[0] = "AUX1";
pThis->m_channelNames[1] = "AUX2";
pThis->m_channelNames[2] = "A1-R1";
pThis->m_channelNames[3] = "A2-R2";
break;
case Preset_Atlantis_4x4: gtk_spin_button_set_value(pThis->m_buttonChannelCount, 8); // 2 EEG channels + 2 AUX + 2 EEG channels + 2 AUX
gtk_combo_box_set_active(pThis->m_comboBoxType, 1); // Atlantis
gtk_combo_box_set_active(pThis->m_comboBoxSamplingRate, 0); // default
//gtk_combo_box_set_active(pThis->m_comboBoxDevice, );
//gtk_combo_box_set_active(pThis->m_comboBoxPreset, );
gtk_combo_box_set_active(pThis->m_comboBoxBaudRate, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxBitDepth, 0); // default
gtk_combo_box_set_active(pThis->m_comboBoxNotchFilters, 0); // default
gtk_widget_set_sensitive(GTK_WIDGET(pThis->m_comboBoxBitDepth), TRUE); // default
pThis->m_rvChannelType.clear();
pThis->m_rvChannelType[0] = ChannelType_AUX;
pThis->m_rvChannelType[1] = ChannelType_AUX;
pThis->m_rvChannelType[2] = ChannelType_EEG;
pThis->m_rvChannelType[3] = ChannelType_EEG;
pThis->m_rvChannelType[4] = ChannelType_AUX;
pThis->m_rvChannelType[5] = ChannelType_AUX;
pThis->m_rvChannelType[6] = ChannelType_EEG;
pThis->m_rvChannelType[7] = ChannelType_EEG;
pThis->m_channelNames[0] = "AUX1";
pThis->m_channelNames[1] = "AUX2";
pThis->m_channelNames[2] = "A1-R1";
pThis->m_channelNames[3] = "A2-R2";
pThis->m_channelNames[4] = "AUX3";
pThis->m_channelNames[5] = "AUX4";
pThis->m_channelNames[6] = "A3-R3";
pThis->m_channelNames[7] = "A4-R4";
break;
}
guardFlag = false;
}
} // namespace
CConfigurationBrainmasterDiscovery::CConfigurationBrainmasterDiscovery(const char* gtkBuilderFilename, uint32_t& rPort, uint32_t& rPreset, uint32_t& rType,
uint32_t& rBaudRate, uint32_t& rSamplingRate, uint32_t& rBitDepth,
uint32_t& rNotchFilters, std::map<uint32_t, uint32_t>& rvChannelType,
std::string& sDeviceSerial, std::string& sDevicePasskey)
: CConfigurationBuilder(gtkBuilderFilename), m_rPort(rPort), m_rPreset(rPreset), m_rType(rType), m_rBaudRate(rBaudRate), m_rSamplingRate(rSamplingRate),
m_rBitDepth(rBitDepth), m_rNotchFilters(rNotchFilters), m_rvChannelType(rvChannelType), m_deviceSerial(sDeviceSerial), m_devicePasskey(sDevicePasskey)
{
m_listStore = gtk_list_store_new(1, G_TYPE_STRING);
}
CConfigurationBrainmasterDiscovery::~CConfigurationBrainmasterDiscovery() { g_object_unref(m_listStore); }
bool CConfigurationBrainmasterDiscovery::preConfigure()
{
if (!CConfigurationBuilder::preConfigure()) { return false; }
const uint32_t port = m_rPort;
m_buttonChannelCount = GTK_SPIN_BUTTON(this->m_nChannels);
m_comboBoxDevice = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_device"));
m_comboBoxPreset = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_device_preset"));
m_comboBoxType = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_type"));
m_comboBoxBaudRate = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_baud_rate"));
m_comboBoxSamplingRate = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_sampling_frequency"));
m_comboBoxBitDepth = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_bit_depth"));
m_comboBoxNotchFilters = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_notch_filters"));
m_pEntryDeviceSerial = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_device_serial"));
m_pEntryDevicePasskey = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_device_passkey"));
g_signal_connect(G_OBJECT(m_buttonChannelCount), "value-changed", G_CALLBACK(on_spin_button_changed), m_comboBoxPreset);
g_signal_connect(G_OBJECT(m_comboBoxPreset), "changed", G_CALLBACK(on_device_preset_changed), this);
g_signal_connect(G_OBJECT(m_comboBoxType), "changed", G_CALLBACK(on_combo_box_changed), m_comboBoxPreset);
g_signal_connect(G_OBJECT(m_comboBoxBaudRate), "changed", G_CALLBACK(on_combo_box_changed), m_comboBoxPreset);
g_signal_connect(G_OBJECT(m_comboBoxSamplingRate), "changed", G_CALLBACK(on_combo_box_changed), m_comboBoxPreset);
g_signal_connect(G_OBJECT(m_comboBoxBitDepth), "changed", G_CALLBACK(on_combo_box_changed), m_comboBoxPreset);
g_signal_connect(G_OBJECT(m_comboBoxNotchFilters), "changed", G_CALLBACK(on_combo_box_changed), m_comboBoxPreset);
g_object_unref(m_listStore);
m_listStore = gtk_list_store_new(1, G_TYPE_STRING);
gtk_combo_box_set_model(m_comboBoxDevice, GTK_TREE_MODEL(m_listStore));
char buffer[1024];
bool selected = false;
gtk_combo_box_append_text(m_comboBoxDevice, "Auto");
for (uint32_t i = 1; i < 17; ++i)
{
sprintf(buffer, "COM%i", i);
gtk_combo_box_append_text(m_comboBoxDevice, buffer);
if (port == i)
{
gtk_combo_box_set_active(m_comboBoxDevice, i);
selected = true;
}
}
if (!selected) { gtk_combo_box_set_active(m_comboBoxDevice, 0); }
switch (m_rType)
{
default:
case Type_Discovery: gtk_combo_box_set_active(m_comboBoxType, 0);
break;
case Type_Atlantis: gtk_combo_box_set_active(m_comboBoxType, 1);
break;
}
switch (m_rBaudRate)
{
default:
case BaudRate_Default: gtk_combo_box_set_active(m_comboBoxBaudRate, 0);
break;
case BaudRate_9600: gtk_combo_box_set_active(m_comboBoxBaudRate, 1);
break;
case BaudRate_115200: gtk_combo_box_set_active(m_comboBoxBaudRate, 2);
break;
case BaudRate_460800: gtk_combo_box_set_active(m_comboBoxBaudRate, 3);
break;
}
switch (m_rSamplingRate)
{
default:
case SamplingFrequency_256: gtk_combo_box_set_active(m_comboBoxSamplingRate, 0);
break;
case SamplingFrequency_512: gtk_combo_box_set_active(m_comboBoxSamplingRate, 1);
break;
case SamplingFrequency_1024: gtk_combo_box_set_active(m_comboBoxSamplingRate, 2);
break;
case SamplingFrequency_2048: gtk_combo_box_set_active(m_comboBoxSamplingRate, 3);
break;
}
switch (m_rBitDepth)
{
default:
case BitDepth_Default: gtk_combo_box_set_active(m_comboBoxBitDepth, 0);
break;
case BitDepth_8: gtk_combo_box_set_active(m_comboBoxBitDepth, 1);
break;
case BitDepth_16: gtk_combo_box_set_active(m_comboBoxBitDepth, 2);
break;
case BitDepth_24: gtk_combo_box_set_active(m_comboBoxBitDepth, 3);
break;
}
switch (m_rNotchFilters)
{
default:
case NotchFilter_Default: gtk_combo_box_set_active(m_comboBoxNotchFilters, 0);
break;
case NotchFilter_Off: gtk_combo_box_set_active(m_comboBoxNotchFilters, 1);
break;
case NotchFilter_50: gtk_combo_box_set_active(m_comboBoxNotchFilters, 2);
break;
case NotchFilter_60: gtk_combo_box_set_active(m_comboBoxNotchFilters, 3);
break;
}
switch (m_rPreset)
{
default:
case Preset_Custom: gtk_combo_box_set_active(m_comboBoxPreset, 0);
break;
case Preset_Discovery_24: gtk_combo_box_set_active(m_comboBoxPreset, 1);
break;
case Preset_Atlantis_4x4: gtk_combo_box_set_active(m_comboBoxPreset, 2);
break;
case Preset_Atlantis_2x2: gtk_combo_box_set_active(m_comboBoxPreset, 3);
break;
}
gtk_entry_set_text(m_pEntryDeviceSerial, m_deviceSerial.c_str());
gtk_entry_set_text(m_pEntryDevicePasskey, m_devicePasskey.c_str());
return true;
}
bool CConfigurationBrainmasterDiscovery::postConfigure()
{
if (m_applyConfig)
{
const int port = gtk_combo_box_get_active(m_comboBoxDevice);
if (port >= 0) { m_rPort = uint32_t(port); }
const int preset = gtk_combo_box_get_active(m_comboBoxPreset);
if (preset >= 0) { m_rPreset = uint32_t(preset); }
const int type = gtk_combo_box_get_active(m_comboBoxType);
if (type >= 0) { m_rType = uint32_t(type); }
const int baudRate = gtk_combo_box_get_active(m_comboBoxBaudRate);
if (baudRate >= 0) { m_rBaudRate = uint32_t(baudRate); }
const int sampling = gtk_combo_box_get_active(m_comboBoxSamplingRate);
if (sampling >= 0) { m_rSamplingRate = uint32_t(sampling); }
const int bitDepth = gtk_combo_box_get_active(m_comboBoxBitDepth);
if (bitDepth >= 0) { m_rBitDepth = uint32_t(bitDepth); }
const int notchFilters = gtk_combo_box_get_active(m_comboBoxNotchFilters);
if (notchFilters >= 0) { m_rNotchFilters = uint32_t(notchFilters); }
m_deviceSerial = gtk_entry_get_text(m_pEntryDeviceSerial);
m_devicePasskey = gtk_entry_get_text(m_pEntryDevicePasskey);
}
if (!CConfigurationBuilder::postConfigure()) { return false; }
return true;
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
@@ -0,0 +1,78 @@
/*
* ovasCConfigurationBrainmasterDiscovery.h
*
* Copyright (c) 2012, Yann Renard. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#pragma once
#if defined TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
#include "../ovasCConfigurationBuilder.h"
#include <gtk/gtk.h>
#include <vector>
#include <string>
#include <map>
namespace OpenViBE {
namespace AcquisitionServer {
class CConfigurationBrainmasterDiscovery final : public CConfigurationBuilder
{
public:
CConfigurationBrainmasterDiscovery(const char* gtkBuilderFilename, uint32_t& rPort, uint32_t& rPreset, uint32_t& rType,
uint32_t& rBaudRate, uint32_t& rSamplingFrequency, uint32_t& rBitDepth, uint32_t& rNotchFilters,
std::map<uint32_t, uint32_t>& rvChannelType, std::string& sDeviceSerial, std::string& sDevicePasskey);
~CConfigurationBrainmasterDiscovery() override;
bool preConfigure() override;
bool postConfigure() override;
GtkSpinButton* m_buttonChannelCount = nullptr;
GtkComboBox* m_comboBoxDevice = nullptr;
GtkComboBox* m_comboBoxPreset = nullptr;
GtkComboBox* m_comboBoxType = nullptr;
GtkComboBox* m_comboBoxBaudRate = nullptr;
GtkComboBox* m_comboBoxSamplingRate = nullptr;
GtkComboBox* m_comboBoxBitDepth = nullptr;
GtkComboBox* m_comboBoxNotchFilters = nullptr;
GtkEntry* m_pEntryDeviceSerial = nullptr;
GtkEntry* m_pEntryDevicePasskey = nullptr;
using CConfigurationBuilder::m_channelNames;
GtkListStore* m_listStore = nullptr;
uint32_t& m_rPort;
uint32_t& m_rPreset;
uint32_t& m_rType;
uint32_t& m_rBaudRate;
uint32_t& m_rSamplingRate;
uint32_t& m_rBitDepth;
uint32_t& m_rNotchFilters;
std::map<uint32_t, uint32_t>& m_rvChannelType;
std::string& m_deviceSerial;
std::string& m_devicePasskey;
std::vector<GtkWidget*> m_sensitiveWidgets;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
@@ -0,0 +1,601 @@
/*
* ovasCDriverBrainmasterDiscovery.cpp
*
* Copyright (c) 2012, Yann Renard. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#if defined TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
#include "ovasCDriverBrainmasterDiscovery.h"
#include "ovasCConfigurationBrainmasterDiscovery.h"
#include "../ovasCConfigurationBuilder.h"
#include <toolkit/ovtk_all.h>
#include "ovas_defines_brainmaster_discovery.h"
namespace OpenViBE {
namespace AcquisitionServer {
extern "C" {
int OvAtlLoginDevice(const char* sSerialNumber, const char* sPassKey);
}
static float decode_24(unsigned char*& rpBuffer)
{
int res = rpBuffer[0] + rpBuffer[1] * 0x100 + rpBuffer[2] * 0x10000;
if (res > 0x800000) { res = res - 0x1000000; }
rpBuffer += 3;
return res * 0.01163f;
}
static float decode_16(unsigned char*& rpBuffer)
{
int res = rpBuffer[0] + rpBuffer[1] * 0x100;
if (res > 0x8000) { res = res - 0x10000; }
rpBuffer += 2;
return res * 0.1983f;
}
static float decode_8(unsigned char*& rpBuffer)
{
int res = rpBuffer[0];
res -= 0x80;
rpBuffer += 1;
return res * 100 / 128.f;
}
static uint32_t next_sync(uint32_t sync)
{
sync++;
sync &= 7;
return sync ? sync : 1;
}
//___________________________________________________________________//
// //
CDriverBrainmasterDiscovery::CDriverBrainmasterDiscovery(IDriverContext& ctx)
: IDriver(ctx)
, m_preset(Preset_Discovery_24)
{
m_deviceSerial = ctx.getConfigurationManager().expand("${AcquisitionServer_Driver_BrainmasterDeviceSerial}").toASCIIString();
m_devicePasskey = ctx.getConfigurationManager().expand("${AcquisitionServer_Driver_BrainmasterDevicePasskey}").toASCIIString();
m_frameDumpFilename = ctx.getConfigurationManager().expand("${AcquisitionServer_Driver_BrainmasterFrameDumpFilename}").toASCIIString();
m_baudRates[BaudRate_9600] = 0x30; // 9600
m_baudRates[BaudRate_115200] = 0x20; // 115200
m_baudRates[BaudRate_460800] = 0x10; // 460800
m_baudRateValues[BaudRate_9600] = 9600; // 9600
m_baudRateValues[BaudRate_115200] = 115200; // 115200
m_baudRateValues[BaudRate_460800] = 460800; // 460800
m_notchsFilters[NotchFilter_Default] = 0; // Off
m_notchsFilters[NotchFilter_Off] = 0; // Off
m_notchsFilters[NotchFilter_50] = 2; // 50 Hz
m_notchsFilters[NotchFilter_60] = 3; // 60 Hz
m_notchFiltersValues[NotchFilter_Default] = 0; // Off
m_notchFiltersValues[NotchFilter_Off] = 0; // Off
m_notchFiltersValues[NotchFilter_50] = 50; // 50 Hz
m_notchFiltersValues[NotchFilter_60] = 60; // 60 Hz
m_bitDepths[BitDepth_8] = 1; // 8 bits
m_bitDepths[BitDepth_16] = 2; // 16 bits
m_bitDepths[BitDepth_24] = 3; // 24 bits
m_bitDepthValues[BitDepth_8] = 8; // 8 bits
m_bitDepthValues[BitDepth_16] = 16; // 16 bits
m_bitDepthValues[BitDepth_24] = 24; // 24 bits
// 0xcc for 2 EEG, 0xff for 2 EEG + 2 AUX
m_channelSelectionMasks[24] = 0xffffff; // Type_Discovery
m_channelSelectionMasks[4] = 0xf; // Type_Atlantis 2x2
m_channelSelectionMasks[8] = 0xff; // Type_Atlantis 4x4
m_bitDepthDecoders[ChannelType_EEG][BitDepth_8] = decode_8; // 8 bits
m_bitDepthDecoders[ChannelType_EEG][BitDepth_16] = decode_16; // 16 bits
m_bitDepthDecoders[ChannelType_EEG][BitDepth_24] = decode_24; // 24 bits
m_bitDepthDecoders[ChannelType_AUX][BitDepth_8] = decode_8; // 8 bits
m_bitDepthDecoders[ChannelType_AUX][BitDepth_16] = decode_16; // 16 bits
m_bitDepthDecoders[ChannelType_AUX][BitDepth_24] = decode_16; // 24 bits
m_startModules[Type_Discovery] = ::DiscStartModule;
m_startModules[Type_Atlantis] = ::AtlStartModule;
m_stopModules[Type_Discovery] = ::DiscStopModule;
m_stopModules[Type_Atlantis] = ::AtlStopModule;
m_header.setSamplingFrequency(256);
m_header.setChannelCount(24);
m_header.setChannelName(0, "Fp1"/*"FP1"*/);
m_header.setChannelName(1, "F3");
m_header.setChannelName(2, "C3");
m_header.setChannelName(3, "P3");
m_header.setChannelName(4, "O1");
m_header.setChannelName(5, "F7");
m_header.setChannelName(6, "T3");
m_header.setChannelName(7, "T5");
m_header.setChannelName(8, "Fz");
m_header.setChannelName(9, "Fp2"/*"FP2"*/);
m_header.setChannelName(10, "F4");
m_header.setChannelName(11, "C4");
m_header.setChannelName(12, "P4");
m_header.setChannelName(13, "O2");
m_header.setChannelName(14, "F8");
m_header.setChannelName(15, "T4");
m_header.setChannelName(16, "T6");
m_header.setChannelName(17, "Cz");
m_header.setChannelName(18, "Pz");
m_header.setChannelName(19, "A2");
m_header.setChannelName(20, "Fpz"/*"FPz"*/);
m_header.setChannelName(21, "Oz");
m_header.setChannelName(22, "AUX1");
m_header.setChannelName(23, "AUX2");
for (size_t i = 0; i < m_header.getChannelCount(); ++i) { m_header.setChannelUnits(i, OVTK_UNIT_Volts, OVTK_FACTOR_Micro); }
}
//___________________________________________________________________//
// //
bool CDriverBrainmasterDiscovery::initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback)
{
uint32_t i;
if (m_driverCtx.isConnected()) { return false; }
if (m_deviceSerial == "" || m_devicePasskey == "")
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "The device serial or passkey were not configured\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error <<
"You can set their value from the configuration pannel or from the following configuration tokens :\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << " - " << CString("AcquisitionServer_Driver_BrainmasterDeviceSerial") << "\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << " - " << CString("AcquisitionServer_Driver_BrainmasterDevicePasskey") << "\n";
return false;
}
switch (m_type)
{
default:
case Type_Discovery: m_baudRateReal = (m_baudRate != BaudRate_Default ? m_baudRate : BaudRate_460800);
m_samplingRateReal = m_samplingRate;
m_bitDepthReal = BitDepth_24;
m_notchFiltersReal = (m_notchFilters != NotchFilter_Default ? m_notchFilters : NotchFilter_Default);
m_frameSize = 3;
m_dataOffset = 3;
break;
case Type_Atlantis: m_baudRateReal = (m_baudRate != BaudRate_Default ? m_baudRate : BaudRate_115200);
m_samplingRateReal = m_samplingRate;
m_bitDepthReal = (m_bitDepth != BitDepth_Default ? m_bitDepth : BitDepth_24);
m_notchFiltersReal = (m_notchFilters != NotchFilter_Default ? m_notchFilters : NotchFilter_Default);
m_frameSize = 1;
m_dataOffset = 1;
break;
}
switch (m_bitDepthReal)
{
default:
case BitDepth_24: for (i = 0; i < m_header.getChannelCount(); ++i)
{
switch (m_channelTypes[i])
{
default:
case ChannelType_EEG: m_frameSize += 3;
break;
case ChannelType_AUX: m_frameSize += 2;
break;
}
}
break;
case BitDepth_16: m_frameSize += m_header.getChannelCount() * 2;
break;
case BitDepth_8: m_frameSize += m_header.getChannelCount();
break;
}
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Computed frame size of " << m_frameSize << " bytes\n";
m_samples.resize(m_header.getChannelCount());
m_buffers.resize(m_frameSize);
m_callback = &callback;
m_nSamplePerSentBlock = nSamplePerSentBlock;
// Sets/Autodetects port
m_portReal = m_port;
if (m_portReal == 0)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Auto detecting COM port...\n";
m_portReal = autoDetectPort();
if (m_portReal == uint32_t(-1))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Port is not set and could not be auto detected, please configure the driver\n";
return false;
}
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Found COM port " << m_portReal << " !\n";
}
// Opens device handle at default speed
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Opening COM port " << m_portReal << " at 9600 bauds\n";
if (!::AtlOpenPort(m_portReal, 9600, nullptr))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not open port " << m_portReal << "\n";
return false;
}
// Writes baud rate
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Setting baud rate to " << m_baudRateValues[m_baudRateReal] << " bauds (code " << m_baudRates[
m_baudRateReal] << ")\n";
if (!::AtlSetBaudRate(m_baudRates[m_baudRateReal]))
{
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not set baud rate\n";
return false;
}
// Closes port (which was at default speed)
::AtlClosePort(m_portReal);
// Opens device handle at targeted speed
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Re-opening COM port " << m_portReal << " at " << m_baudRateValues[m_baudRateReal] <<
" bauds (code " << m_baudRates[m_baudRateReal] << ")\n";
if (!::AtlOpenPort(m_portReal, m_baudRateValues[m_baudRateReal], nullptr))
// if(!::AtlOpenPort(m_portReal, 9600, nullptr))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not open port " << m_portReal << "\n";
return false;
}
// Logs in the device
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Logging in the device...\n";
const int code = OvAtlLoginDevice(m_deviceSerial.c_str(), m_devicePasskey.c_str());
if (!code)
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not log in device (error code was " << uint32_t(code) << ")\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Please check the device serial and passkey configuration\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error <<
"You can set their value from the configuration pannel or from the following configuration tokens :\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << " - " << CString("AcquisitionServer_Driver_BrainmasterDeviceSerial") << " (was set to [" <<
m_deviceSerial.c_str() << "])\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << " - " << CString("AcquisitionServer_Driver_BrainmasterDevicePasskey") << " (was set to [" <<
m_devicePasskey.c_str() << "])\n";
if (!checkDeviceSerial(m_deviceSerial))
m_driverCtx.getLogManager() << Kernel::LogLevel_Error <<
"By the way, serial seems to be malformed, it is supposed to be XXXXX with each X be a digit\n";
if (!checkDevicePasskey(m_devicePasskey))
m_driverCtx.getLogManager() << Kernel::LogLevel_Error <<
"By the way, passkey seems to be malformed, it is supposed to be XXXX-XXXX-XXXX with each X be a digit or a letter\n";
return false;
}
// Reads firmware version
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Successfully opened device on port " << m_portReal << " | Firware nr : " <<
uint32_t(AtlQueryFirmware(0)) << "\n";
// Writes notch filters
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Setting notch filters to " << m_notchFiltersValues[m_notchFiltersReal] << " (code " <<
m_notchsFilters
[m_notchFiltersReal] << ")...\n";
if (!::AtlSetNotchFilters(m_notchsFilters[m_notchFiltersReal]))
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not set notch filters\n";
return false;
}
// Writes bit depth
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Setting bit depth to " << m_bitDepthValues[m_bitDepthReal] << " bits (code " << m_bitDepths[
m_bitDepthReal] << ")...\n";
if (!::AtlSetBytesPerSample(m_bitDepths[m_bitDepthReal]))
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not set bytes per sample\n";
return false;
}
// Selects all the channels
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Selecting all channels with channel mask " << m_channelSelectionMasks[m_header.getChannelCount()]
<<
"...\n";
if (!::AtlSelectChannels(m_channelSelectionMasks[m_header.getChannelCount()]))
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not select all the channels\n";
return false;
}
// Clears special data
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Clearing specials...\n";
if (!::AtlClearSpecials())
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not clear special data selection\n";
return false;
}
// Poking special code for Atlantis 4x4
if (m_header.getChannelCount() == 8)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Poking special code for Atlantis 4x4...\n";
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << uint32_t(AtlPoke(0xc006, 0x00)) <<
"\n"; // Sets internal sampling rate set to 512 Hz - This hack solves the EEG chan 3 & 4 flat lines issue
// m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << uint32_t(AtlPoke(0xb607, 0xff)) << "\n"; // ATC_CHANOUTMASK
// m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << uint32_t(AtlPoke(0xb608, 0x20)) << "\n"; // ATC_ADCMODE
// m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << uint32_t(AtlPoke(0xb7e9, 0x03)) << "\n"; // ??? Bit mode ?
}
// serialn_p ::AtlQuerySerialNumber(int auth)
// Actually starts the acquisition
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Starting module !\n";
if (!m_startModules[m_type]())
{
::AtlSetBaudRate(m_baudRates[BaudRate_9600]);
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not start module\n";
return false;
}
m_syncByte = 1;
// Preparing optional frame dump
if (m_frameDumpFilename == "")
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Won't dump frames\n";
m_frameDumpFlag = false;
}
else
{
FILE* file = fopen(m_frameDumpFilename.c_str(), "wb");
if (file)
{
m_frameDumpFlag = true;
fclose(file);
m_driverCtx.getLogManager() << Kernel::LogLevel_Trace << "Will dump frames in [" << m_frameDumpFilename << "]\n";
}
else
{
m_frameDumpFlag = false;
m_driverCtx.getLogManager() << Kernel::LogLevel_Warning << "Should have dumped frames in [" << m_frameDumpFilename <<
"] but file can't be opened for writing !\n";
}
}
return true;
}
bool CDriverBrainmasterDiscovery::start()
{
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
return true;
}
bool CDriverBrainmasterDiscovery::loop()
{
if (!m_driverCtx.isConnected()) { return false; }
if (!m_driverCtx.isStarted()) { return true; }
bool gotData = false;
for (uint32_t i = 0; i < m_nSamplePerSentBlock; ++i)
{
// Updates Sync bits
m_syncByte = next_sync(m_syncByte);
// Searches for Sync bits
this->read(&m_buffers[0], 1);
if (((m_buffers[0] >> 5) & 7) != m_syncByte)
{
// Needs resync
uint32_t sync = this->sync();
if (sync != uint32_t(-1)) { m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Resynced by " << sync << " byte(s) !\n"; }
else { m_driverCtx.getLogManager() << Kernel::LogLevel_ImportantWarning << "Could not resync, did not find the sync bytes !\n"; }
m_wasLastFrameCorrect = false;
}
else
{
// Sends samples if last frame was correct
if (m_wasLastFrameCorrect)
{
m_callback->setSamples(&m_samples[0], 1);
gotData = true;
}
// Assumed synced stream - Reads leading bytes
this->read(&m_buffers[1], m_buffers.size() - 1);
#if 1
// For debug purpose
if (m_frameDumpFlag)
{
FILE* file = fopen(m_frameDumpFilename.c_str(), "ab");
if (file)
{
fprintf(file, "Frame : ");
for (uint32_t i = 0; i < m_buffers.size(); ++i) { fprintf(file, "0x%02x ", m_buffers[i]); }
fprintf(file, "\n");
fclose(file);
}
else
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Warning << "Unexpected: Could not open dump file [" << m_frameDumpFilename <<
"] for writing\n";
m_frameDumpFlag = false;
}
}
#endif
// Converts new buffer to samples
unsigned char* buffer = &m_buffers[m_dataOffset];
for (uint32_t j = 0; j < m_samples.size(); ++j) { m_samples[j] = m_bitDepthDecoders[m_channelTypes[j]][m_bitDepthReal](buffer); }
m_wasLastFrameCorrect = true;
}
}
if (gotData) { m_driverCtx.correctDriftSampleCount(m_driverCtx.getSuggestedDriftCorrectionSampleCount()); }
return true;
}
bool CDriverBrainmasterDiscovery::read(unsigned char* frame, uint32_t size)
{
const uint32_t count = size;
uint32_t idx = 0;
while (idx != count)
{
int iCode = ::AtlReadData(frame + idx, count - idx);
if (iCode >= 0) { idx += iCode; }
}
return true;
}
uint32_t CDriverBrainmasterDiscovery::sync()
{
std::vector<unsigned char> buffer;
buffer.resize(m_buffers.size() * 4);
bool finished = false;
uint32_t nSync = 0;
uint32_t i = 0;
while (!finished && i < 16)
{
i++;
this->read(&buffer[0], buffer.size());
for (uint32_t i = 0; i < m_buffers.size() && !finished; ++i)
{
uint32_t syncCandidate[4];
syncCandidate[0] = buffer[i + 0 * m_buffers.size()] >> 5;
syncCandidate[1] = buffer[i + 1 * m_buffers.size()] >> 5;
syncCandidate[2] = buffer[i + 2 * m_buffers.size()] >> 5;
syncCandidate[3] = buffer[i + 3 * m_buffers.size()] >> 5;
if (next_sync(syncCandidate[0]) == syncCandidate[1]
&& next_sync(syncCandidate[1]) == syncCandidate[2]
&& next_sync(syncCandidate[2]) == syncCandidate[3])
{
this->read(&buffer[0], i);
m_syncByte = syncCandidate[3];
nSync = i;
finished = true;
}
}
}
#if 1
// For debug purpose
if (m_frameDumpFlag)
{
FILE* file = fopen(m_frameDumpFilename.c_str(), "ab");
if (file)
{
fprintf(file, "Syncing...\n");
for (uint32_t i = 0; i < buffer.size(); ++i)
{
fprintf(file, "0x%02x ", buffer[i]);
if (((i + 1) % m_buffers.size()) == 0) { fprintf(file, "\n"); }
}
fclose(file);
}
else
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Warning << "Unexpected: Could not open dump file [" << m_frameDumpFilename <<
"] for writing\n";
m_frameDumpFlag = false;
}
}
#endif
return finished ? nSync : uint32_t(-1);
}
bool CDriverBrainmasterDiscovery::stop()
{
if (!m_driverCtx.isConnected() || !m_driverCtx.isStarted()) { return false; }
return true;
}
bool CDriverBrainmasterDiscovery::uninitialize()
{
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
// Stops acquisition
if (!m_stopModules[m_type]())
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could stop module\n";
return false;
}
// Writes baud rate back to 9600
if (!::AtlSetBaudRate(m_baudRates[BaudRate_9600]))
{
::AtlClosePort(m_portReal);
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not set baud rate\n";
return false;
}
// Closes device handle
if (!::AtlClosePort(m_portReal))
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Could not close port " << m_portReal << "\n";
return false;
}
return true;
}
//___________________________________________________________________//
// //
bool CDriverBrainmasterDiscovery::configure()
{
CConfigurationBrainmasterDiscovery config(Directories::getDataDir() + "/applications/acquisition-server/interface-Brainmaster-Discovery.ui",
m_port, m_preset, m_type, m_baudRate, m_samplingRate, m_bitDepth,
m_notchFilters, m_channelTypes, m_deviceSerial, m_devicePasskey);
if (!config.configure(m_header)) { return false; }
return true;
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
@@ -0,0 +1,107 @@
/*
* ovasCDriverBrainmasterDiscovery.h
*
* Copyright (c) 2012, Yann Renard. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#pragma once
#if defined TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
#include "ovasIDriver.h"
#include "../ovasCHeader.h"
#include <vector>
#include <map>
#include <string>
namespace OpenViBE {
namespace AcquisitionServer {
/**
* \class CDriverBrainmasterDiscovery
* \author Yann Renard
*/
class CDriverBrainmasterDiscovery final : public IDriver
{
public:
explicit CDriverBrainmasterDiscovery(IDriverContext& ctx);
void release() { delete this; }
const char* getName() override { return "Brainmaster Discovery and Atlantis"; }
bool initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback) override;
bool uninitialize() override;
bool start() override;
bool stop() override;
bool loop() override;
bool read(unsigned char* frame, uint32_t size);
uint32_t sync();
bool isConfigurable() override { return true; }
bool configure() override;
const IHeader* getHeader() override { return &m_header; }
protected:
IDriverCallback* m_callback = nullptr;
CHeader m_header;
uint32_t m_nSamplePerSentBlock = 0;
std::string m_deviceSerial;
std::string m_devicePasskey;
std::string m_frameDumpFilename;
bool m_frameDumpFlag = false;
uint32_t m_port = 0;
uint32_t m_portReal = 0;
uint32_t m_preset = 0;
uint32_t m_type = 0;
uint32_t m_baudRate = 0;
uint32_t m_baudRateReal = 0;
uint32_t m_samplingRate = 0;
uint32_t m_samplingRateReal = 0;
uint32_t m_bitDepth = 0;
uint32_t m_bitDepthReal = 0;
uint32_t m_notchFilters = 0;
uint32_t m_notchFiltersReal = 0;
uint32_t m_frameSize = 0;
uint32_t m_dataOffset = 0;
std::map<uint32_t, uint32_t> m_baudRates;
std::map<uint32_t, uint32_t> m_baudRateValues;
std::map<uint32_t, uint32_t> m_notchsFilters;
std::map<uint32_t, uint32_t> m_notchFiltersValues;
std::map<uint32_t, uint32_t> m_bitDepths;
std::map<uint32_t, uint32_t> m_bitDepthValues;
std::map<uint32_t, uint32_t> m_channelTypes;
std::map<uint32_t, uint32_t> m_channelSelectionMasks;
std::map<uint32_t, std::map<uint32_t, float (*)(unsigned char*&)>> m_bitDepthDecoders;
std::map<uint32_t, int (*)()> m_startModules;
std::map<uint32_t, int (*)()> m_stopModules;
std::vector<float> m_samples;
std::vector<unsigned char> m_buffers;
uint32_t m_syncByte = 0;
bool m_wasLastFrameCorrect = false;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
@@ -0,0 +1,127 @@
/*
* ovas_defines_brainmaster_discovery.h
*
* Copyright (c) 2012, Yann Renard. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#pragma once
#if defined TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI
#include "ovasIDriver.h"
#include "CMKRDLLU.H"
#include <string>
namespace OpenViBE {
namespace AcquisitionServer {
typedef enum
{
Preset_Custom=0,
Preset_Discovery_24=1,
Preset_Atlantis_4x4=2,
Preset_Atlantis_2x2=3,
Type_Discovery=0,
Type_Atlantis=1,
ChannelType_EEG=0,
ChannelType_AUX=1,
BaudRate_Default=0,
BaudRate_9600=1,
BaudRate_115200=2,
BaudRate_460800=3,
NotchFilter_Default=0,
NotchFilter_Off=1,
NotchFilter_50=2,
NotchFilter_60=3,
BitDepth_Default=0,
BitDepth_8=1,
BitDepth_16=2,
BitDepth_24=3,
SamplingFrequency_256=0,
SamplingFrequency_512=1,
SamplingFrequency_1024=2,
SamplingFrequency_2048=3,
} EParameter;
inline size_t autoDetectPort(const size_t startPort = 1, const size_t stopPort = 16, const size_t fallback = size_t(-1))
{
for (size_t i = startPort; i <= stopPort; ++i)
{
const BOOL res = ::AtlOpenPort(i, /*m_baudRate*/ 0, nullptr);
::AtlClosePort(i);
if (res) { return i; }
}
return fallback;
}
// returns true on success
// returns false on error
inline bool checkDeviceSerial(const std::string& serial)
{
// Checks length
if (serial.length() != 5) { return false; }
// Checks digits
for (size_t i = 0; i < serial.length(); ++i) { if (serial[i] < '0' || serial[i] > '9') { return false; } }
// First digit gives device kind
switch (serial[0])
{
case '3': // Atlantis
case '4': // Atlantis
case '6': // Discovery
default: break;
}
// Everything's fine
return true;
}
// returns true on success
// returns false on error
inline bool checkDevicePasskey(const std::string& passkey)
{
// Checks length -- other checks are hardcoded assuming length is 15
if (passkey.length() != 14) { return false; }
// Checks separators
if (passkey[4] != '-' || passkey[9] != '-') { return false; }
// Checks alpha-nums
for (size_t i = 0; i < 3; ++i)
{
for (size_t j = 0; j < 4; ++j)
{
const size_t k = i * 5 + j;
if ((passkey[k] < '0' || passkey[k] > '9') && (passkey[k] < 'a' || passkey[k] > 'z')
&& (passkey[k] < 'A' || passkey[k] > 'Z')) { return false; }
}
}
// Everything's fine
return true;
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyBrainmasterCodeMakerAPI