Commit 6770e6cf authored by Jussi Lindgren's avatar Jussi Lindgren
Browse files

Drivers: Impendance check support for the EEGO driver

+ Minor cleanup

Code contributed by Steffen Heimes / eemagine
parent 25dc34a8
......@@ -9,98 +9,6 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkListStore" id="SamplingRateModel">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">500</col>
</row>
<row>
<col id="0" translatable="yes">512</col>
</row>
<row>
<col id="0" translatable="yes">1000</col>
</row>
<row>
<col id="0" translatable="yes">1024</col>
</row>
<row>
<col id="0" translatable="yes">2000</col>
</row>
<row>
<col id="0" translatable="yes">2048</col>
</row>
<row>
<col id="0" translatable="yes">4000</col>
</row>
<row>
<col id="0" translatable="yes">4096</col>
</row>
<row>
<col id="0" translatable="yes">8000</col>
</row>
<row>
<col id="0" translatable="yes">8192</col>
</row>
<row>
<col id="0" translatable="yes">16000</col>
</row>
<row>
<col id="0" translatable="yes">16384</col>
</row>
</data>
</object>
<object class="GtkListStore" id="SignalRangeModelBIP">
<columns>
<!-- column-name SignalRanges -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">350</col>
</row>
<row>
<col id="0" translatable="yes">700</col>
</row>
<row>
<col id="0" translatable="yes">1500</col>
</row>
<row>
<col id="0" translatable="yes">4000</col>
</row>
</data>
</object>
<object class="GtkListStore" id="SignalRangeModelEEG">
<columns>
<!-- column-name SignalRanges -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">150</col>
</row>
<row>
<col id="0" translatable="yes">750</col>
</row>
<row>
<col id="0" translatable="yes">1000</col>
</row>
</data>
</object>
<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="GtkWindow" id="dummy_settings">
<property name="can_focus">False</property>
<child>
......@@ -439,6 +347,171 @@
<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>
<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>
<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>
<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>
<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>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
<property name="visible">True</property>
......@@ -456,6 +529,98 @@
</object>
</child>
</object>
<object class="GtkListStore" id="SamplingRateModel">
<columns>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">500</col>
</row>
<row>
<col id="0" translatable="yes">512</col>
</row>
<row>
<col id="0" translatable="yes">1000</col>
</row>
<row>
<col id="0" translatable="yes">1024</col>
</row>
<row>
<col id="0" translatable="yes">2000</col>
</row>
<row>
<col id="0" translatable="yes">2048</col>
</row>
<row>
<col id="0" translatable="yes">4000</col>
</row>
<row>
<col id="0" translatable="yes">4096</col>
</row>
<row>
<col id="0" translatable="yes">8000</col>
</row>
<row>
<col id="0" translatable="yes">8192</col>
</row>
<row>
<col id="0" translatable="yes">16000</col>
</row>
<row>
<col id="0" translatable="yes">16384</col>
</row>
</data>
</object>
<object class="GtkListStore" id="SignalRangeModelBIP">
<columns>
<!-- column-name SignalRanges -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">350</col>
</row>
<row>
<col id="0" translatable="yes">700</col>
</row>
<row>
<col id="0" translatable="yes">1500</col>
</row>
<row>
<col id="0" translatable="yes">4000</col>
</row>
</data>
</object>
<object class="GtkListStore" id="SignalRangeModelEEG">
<columns>
<!-- column-name SignalRanges -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">150</col>
</row>
<row>
<col id="0" translatable="yes">750</col>
</row>
<row>
<col id="0" translatable="yes">1000</col>
</row>
</data>
</object>
<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="GtkListStore" id="model1">
<columns>
<!-- column-name gchararray -->
......@@ -570,7 +735,7 @@
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">9</property>
<property name="n_rows">10</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
......@@ -853,6 +1018,32 @@
<property name="bottom_attach">9</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">9</property>
<property name="bottom_attach">10</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="active">True</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">9</property>
<property name="bottom_attach">10</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
......
......@@ -87,51 +87,68 @@ boolean CDriverEEGO::initialize(
if(m_rDriverContext.isConnected()) return false;
if(!m_oHeader.isChannelCountSet()||!m_oHeader.isSamplingFrequencySet()) return false;
// Builds up a buffer to store
// acquired samples. This buffer
// will be sent to the acquisition
// server later...
m_pSample=new float32[m_oHeader.getChannelCount()*ui32SampleCountPerSentBlock];
m_ui32SamplesInBuffer=0;
if(!m_pSample)
try
{
delete [] m_pSample;
m_pSample=NULL;
return false;
}
// To initialize we need to locate the path of the DLL
// Create path to the dll
const OpenViBE::CString l_oLibDir=Directories::getBinDir()+"\\eego-SDK.dll";
auto l_sPath=l_oLibDir.toASCIIString();
// Builds up a buffer to store
// acquired samples. This buffer
// will be sent to the acquisition
// server later...
m_pSample = new float32[m_oHeader.getChannelCount()*ui32SampleCountPerSentBlock];
m_ui32SamplesInBuffer = 0;
if (!m_pSample)
{
throw std::exception("Failed to allocate sample buffer");
}
// create the amplifier factory
es::factory fact(l_sPath);
// create the amplifier factory
// To initialize we need to locate the path of the DLL
// Create path to the dll
const OpenViBE::CString l_oLibDir = Directories::getBinDir() + "\\eego-SDK.dll";
auto l_sPath = l_oLibDir.toASCIIString();
m_rDriverContext.getLogManager() << LogLevel_Debug << "SDK dll path: " << l_sPath << "\n";
es::factory fact(l_sPath);
// to check what is going on case of error; Log version
const auto version=fact.getVersion();
m_rDriverContext.getLogManager()<<LogLevel_Info<<"EEGO RT: Version: "<<version.major<<"."<<version.minor<<"."<<version.micro<<"."<<version.build<<"\n";
// to check what is going on case of error; Log version
const auto version = fact.getVersion();
m_rDriverContext.getLogManager() << LogLevel_Info << "EEGO RT: Version: " << version.major << "." << version.minor << "." << version.micro << "." << version.build << "\n";
// Get the amplifier. If none is connected an exception will be thrown
try
{
m_pAmplifier=fact.getAmplifier();
// Get the amplifier. If none is connected an exception will be thrown
try
{
m_pAmplifier = fact.getAmplifier();
}
catch (const std::exception& ex)
{
m_rDriverContext.getLogManager() << LogLevel_Warning << "Failure to get an amplifier! Reason: " << ex.what() << "\n";
throw;
}
if (m_rDriverContext.isImpedanceCheckRequested())
{
// After init we are in impedance mode until the recording is started
OpenViBE::uint64 l_i64MaskEEG = getRefChannelMask(); // Only the reference channels can be measured
m_pStream = m_pAmplifier->OpenImpedanceStream(l_i64MaskEEG);
}
}
catch (const std::exception& ex)
{
m_rDriverContext.getLogManager()<<LogLevel_Warning<<"Failure to get an amplifier! Reason: "<<ex.what()<<"\n";
m_rDriverContext.getLogManager() << LogLevel_Error << "Failed to initialize the driver. Exception: " << ex.what() << "\n";
// Cleanup
delete[] m_pSample;
m_pSample = NULL;
delete m_pAmplifier;
m_pAmplifier = NULL;
delete m_pStream;
m_pStream = NULL;
return false;
}
// Saves parameters
// Save parameters
m_pCallback=&rCallback;
m_ui32SampleCountPerSentBlock=ui32SampleCountPerSentBlock;
// After init we are in impedance mode until the recording is started
OpenViBE::uint64 l_i64MaskEEG=getRefChannelMask(); // Only the reference channels can be measured
m_pStream=m_pAmplifier->OpenImpedanceStream(l_i64MaskEEG);
return true;
}
......@@ -264,11 +281,16 @@ boolean CDriverEEGO::start(void)
boolean CDriverEEGO::loop(void)
{
if(!m_rDriverContext.isConnected()) return false;
if (!m_rDriverContext.isStarted()
&& !m_rDriverContext.isImpedanceCheckRequested())
return true; // Nothing to be done here!
if(!m_pStream) return false;
// Check if we really provide enough channels
// When doing impedance only the normal EEG channels are tested. This is fine and handled.
if(m_pStream->getChannelList().size() < m_oHeader.getChannelCount()
&& m_rDriverContext.isStarted()) // !started -> impedance
&& m_rDriverContext.isStarted()) // !started -> impedance
{
m_rDriverContext.getLogManager()<<LogLevel_Error<<"The amplifier got asked for more channels than it could provide";
return false;
......@@ -340,25 +362,26 @@ boolean CDriverEEGO::loop(void)
}
else // Impedance
{
// Get the impedance data, here the data is always the most current state.
// Get the impedance data, here the data is always the most current state.
// The method can block if impedance still needs to be calculated.
eemagine::sdk::buffer data;
try
{
data=m_pStream->getData();
data = m_pStream->getData();
}
catch(const std::exception& ex)
catch (const std::exception& ex)
{
m_rDriverContext.getLogManager()<<LogLevel_Error<<"Error fetching data: "<<ex.what();
m_rDriverContext.getLogManager() << LogLevel_Error << "Error fetching data: " << ex.what();
return false;
}
// We have to take care not to r/w over any boundary.
OpenViBE::uint32 minChannels=min(data.getChannelCount(), m_oHeader.getChannelCount());
for(OpenViBE::uint32 channel=0; channel < minChannels; channel++)
OpenViBE::uint32 minChannels = min(data.getChannelCount(), m_oHeader.getChannelCount());
for (OpenViBE::uint32 channel = 0; channel < minChannels; channel++)
{
m_rDriverContext.updateImpedance(channel, data.getSample(channel, 0));
}
}
return true;
......@@ -375,7 +398,10 @@ boolean CDriverEEGO::stop(void)
// ...
delete m_pStream;
m_pStream=NULL; // Deletion of the stream stops the streaming.
m_pStream=m_pAmplifier->OpenImpedanceStream(getRefChannelMask()); // And we can stream Impedances once more.
if (m_rDriverContext.isImpedanceCheckRequested())
{
m_pStream = m_pAmplifier->OpenImpedanceStream(getRefChannelMask()); // And we can stream Impedances once more.
}
return true;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment