diff --git a/Builds/VisualStudio2012/open-ephys.sln b/Builds/VisualStudio2012/open-ephys.sln index 520a8d855d09a997cfccb769049bb0e4c270ef34..61074c0e04aebb4f1d48dd95b47ccd0a86ed9f09 100644 --- a/Builds/VisualStudio2012/open-ephys.sln +++ b/Builds/VisualStudio2012/open-ephys.sln @@ -1,29 +1,21 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" +Project("{5A05F353-1D63-394C-DFB0-981BB2309002}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Debug64|Win32 = Debug64|Win32 - Debug64|x64 = Debug64|x64 Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - Release64|Win32 = Release64|Win32 + Debug64|x64 = Debug64|x64 Release64|x64 = Release64|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.ActiveCfg = Debug|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.Build.0 = Debug|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|x64.ActiveCfg = Debug|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|Win32.ActiveCfg = Debug64|x64 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.ActiveCfg = Release|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.Build.0 = Release|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|x64.ActiveCfg = Release|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|Win32.ActiveCfg = Release64|x64 + {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64 + {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.ActiveCfg = Release64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.Build.0 = Release64|x64 EndGlobalSection diff --git a/Resources/DLLs/InstallEcubeApi_0_11.exe b/Resources/DLLs/InstallEcubeApi_0_11.exe deleted file mode 100644 index e27b63318da3f5a9298686ac4bdae24787667659..0000000000000000000000000000000000000000 Binary files a/Resources/DLLs/InstallEcubeApi_0_11.exe and /dev/null differ diff --git a/Resources/DLLs/InstallEcubeApi_0_12.exe b/Resources/DLLs/InstallEcubeApi_0_12.exe new file mode 100644 index 0000000000000000000000000000000000000000..80767facebc329c985affedfb47f9756a25d8e6c Binary files /dev/null and b/Resources/DLLs/InstallEcubeApi_0_12.exe differ diff --git a/Source/Processors/ChannelMappingNode/ChannelMappingEditor.cpp b/Source/Processors/ChannelMappingNode/ChannelMappingEditor.cpp index 027b704dfcfcdb4b46bc3b89b0ebde900541b6bc..436332444b978252a39b105413b1731e7ec26aab 100644 --- a/Source/Processors/ChannelMappingNode/ChannelMappingEditor.cpp +++ b/Source/Processors/ChannelMappingNode/ChannelMappingEditor.cpp @@ -848,6 +848,7 @@ void ChannelMappingEditor::mouseUp(const MouseEvent& e) setChannelPosition(i,electrodeButtons[i]->getChannelNum()); } setConfigured(true); + getEditorViewport()->makeEditorVisible(this, false, true); } } diff --git a/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp b/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp index 1fa005652daa87683bc7dc13d390a6fe0d3af56d..fd632c8eef455da9859b51b0e2991ef8a3866f46 100644 --- a/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp +++ b/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp @@ -68,6 +68,25 @@ void ChannelMappingNode::updateSettings() if (getNumInputs() > 0) channelBuffer.setSize(getNumInputs(), 10000); + previousChannelCount = getNumInputs(); + if (editorIsConfigured) + { + OwnedArray<Channel> tempArray; + channels.swapWith(tempArray); + j=0; + for (int i=0; i < getNumInputs(); i++) + { + int realChan = channelArray[i]; + if (enabledChannelArray[realChan]) + { + channels.add(tempArray[realChan]); + j++; + } + } + tempArray.clear(false); + settings.numOutputs=j; + } + /* if (getNumInputs() != previousChannelCount) { previousChannelCount = getNumInputs(); @@ -103,7 +122,7 @@ void ChannelMappingNode::updateSettings() } } settings.numOutputs=j; - } + }*/ } diff --git a/Source/Processors/DataThreads/EcubeThread.cpp b/Source/Processors/DataThreads/EcubeThread.cpp index 02a00cd3d9a5703bfc6e05e3eb6889c985a0181c..84f0a59c12497b09958c5fde62f21f603327227b 100644 --- a/Source/Processors/DataThreads/EcubeThread.cpp +++ b/Source/Processors/DataThreads/EcubeThread.cpp @@ -48,6 +48,8 @@ public: IEcubeAnalogAcquisitionPtr pStrmA; IEcubeDigitalInputStreamingPtr pStrmD; HeapBlock<float, true> interleaving_buffer; + HeapBlock<uint64_t, true> event_buffer; + HeapBlock<uint32_t, true> bit_conversion_tables; bool buf_timestamp_locked; unsigned long buf_timestamp; uint64 buf_timestamp64; @@ -59,7 +61,37 @@ static const char bits_port0[16] = { 23, 22, -1, 14, 11, -1, -1, 28, 12, 10, 27, static const char bits_port1[16] = { 20, 21, 19, 18, 13, 6, 4, 5, 3, 2, -1, -1, 29, -1, 24, 25 }; static const char bits_port2[16] = { 16, 17, 15, 8, 9, 7, 0, 1, 31, 30, -1, -1, -1, -1, -1, -1 }; +// Builds bit conversion table for 8 bits of raw data +void build_bit_conversion_table(uint32_t* table, const char* bits) +{ + for (uint16_t i = 0; i < 256; i++) + { + uint8_t is = i; + uint32_t outval = 0; + for (uint16_t j = 0; j < 8; j++) + { + if ((is & 1) && bits[j]>=0) + { + outval |= (uint32_t)1<<bits[j]; + } + is >>= 1; + } + table[i] = outval; + } +} +void build_bit_conversion_tables(uint32_t* tables) +{ + // Bit conversion tables have 256 uint64s for each 8 bits of ecube ports + // Each sparse 16-bit port has two such tables + // The structure in memory is {tbl_port0l, tbl_port0h, tbl_port1l, tbl_port1h, tbl_port2l, tbl_port2h) + build_bit_conversion_table(tables , bits_port0); + build_bit_conversion_table(tables + 0x100, bits_port0 + 8); + build_bit_conversion_table(tables + 0x200, bits_port1); + build_bit_conversion_table(tables + 0x300, bits_port1 + 8); + build_bit_conversion_table(tables + 0x400, bits_port2); + build_bit_conversion_table(tables + 0x500, bits_port2 + 8); +} static std::vector<std::wstring> SafeArrayToVecStr(SAFEARRAY* sa) { @@ -241,6 +273,10 @@ EcubeThread::EcubeThread(SourceNode* sn) : DataThread(sn), numberingScheme(1), a dataBuffer = new DataBuffer(64, 10000); // Create the interleaving buffer based on the number of digital ports pDevInt->interleaving_buffer.malloc(sizeof(float)* 1500 * 64); + // Create the analog of interleaving buffer in packed format (int64) + pDevInt->event_buffer.malloc(sizeof(uint64_t)* 1500); + pDevInt->bit_conversion_tables.malloc(sizeof(uint32_t)* 0x600); + build_bit_conversion_tables(pDevInt->bit_conversion_tables); } else throw std::runtime_error("Invlid module selection"); @@ -338,6 +374,14 @@ int EcubeThread::getNumChannels() return pDevInt->n_channel_objects; } +int EcubeThread::getNumEventChannels() +{ + if (pDevInt->data_format == EcubeDevInt::dfDigital) + return 64; + else + return 0; +} + float EcubeThread::getSampleRate() { return m_samplerate; @@ -461,7 +505,7 @@ bool EcubeThread::updateBuffer() int64 cts = pDevInt->buf_timestamp64 / 3200; // Convert eCube 80MHz timestamp into a 25kHz timestamp for (unsigned long j = 0; j < pDevInt->int_buf_size; j++) { - dataBuffer->addToBuffer(pDevInt->interleaving_buffer + j*64, &cts, &eventCode, 1); + dataBuffer->addToBuffer(pDevInt->interleaving_buffer + j*64, &cts, pDevInt->event_buffer+j, 1); cts++; } // Update the 64-bit timestamp, take account of its wrap-around @@ -477,32 +521,44 @@ bool EcubeThread::updateBuffer() pDevInt->buf_timestamp_locked = true; // Clear the interleaving buffer within the new packet's size memset(pDevInt->interleaving_buffer, 0, sizeof(float)*datasize*64); + // Clear the event buffer as well + memset(pDevInt->event_buffer, 0, sizeof(uint64_t)*datasize); } // Convert data from ecube buffer into the interleaving buffer format chid = chit->second; // Adjust the channel id to become the channel index unsigned char* dp = ab->GetDataPointer(); const uint16_t* pData = (const uint16_t*)dp; const char* pbits; + const uint32_t* pconvtbl; switch (chid) { case 0: case 3: pbits = bits_port0; + pconvtbl = pDevInt->bit_conversion_tables; break; case 1: case 4: pbits = bits_port1; + pconvtbl = pDevInt->bit_conversion_tables+0x200; break; case 2: case 5: default: pbits = bits_port2; + pconvtbl = pDevInt->bit_conversion_tables + 0x400; break; } int bitchn_offset = chid >= 3 ? 32 : 0; + uint8_t dword_shift = chid>=3 ? 32 : 0; for (unsigned long j = 0; j < datasize; j++) { uint16_t wrd = pData[j]; + + // Convert the word into packed 32-bit representation for this port + uint32_t packedwrd = pconvtbl[wrd & 0xFF] | pconvtbl[0x100 + (wrd >> 8)]; + pDevInt->event_buffer[j] |= (uint64_t)packedwrd << dword_shift; + uint16_t msk = 1; for (unsigned long k = 0; k < 16; k++) { diff --git a/Source/Processors/DataThreads/EcubeThread.h b/Source/Processors/DataThreads/EcubeThread.h index d1c0495688a3d27f394252774eca2aba93a5af49..e79fd39c0c3356225929b20caa08711d14ff63d5 100644 --- a/Source/Processors/DataThreads/EcubeThread.h +++ b/Source/Processors/DataThreads/EcubeThread.h @@ -76,6 +76,9 @@ public: /** Returns the number of continuous channels the data source can provide.*/ virtual int getNumChannels(); + /** Returns the number of event channels of the data source.*/ + virtual int getNumEventChannels(); + /** Returns the sample rate of the data source.*/ virtual float getSampleRate(); diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp index 1540782c3cbde6fa85a0cb25e034aa65fda930fd..fef3567156268fe7a9be2ce97d531ae2a6bd9b4c 100755 --- a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp +++ b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp @@ -329,6 +329,15 @@ void LfpDisplayCanvas::update() resized(); } + else + { + for (int i = 0; i < processor->getNumInputs(); i++) + { + lfpDisplay->channels[i]->updateType(); + lfpDisplay->channelInfo[i]->updateType(); + } + + } } @@ -1538,6 +1547,12 @@ LfpChannelDisplay::~LfpChannelDisplay() } +void LfpChannelDisplay::updateType() +{ + type = canvas->getChannelType(chan); + typeStr = canvas->getTypeName(type); +} + void LfpChannelDisplay::setEnabledState(bool state) { @@ -1848,6 +1863,13 @@ LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, LfpDispl } +void LfpChannelDisplayInfo::updateType() +{ + type = canvas->getChannelType(chan); + typeStr = canvas->getTypeName(type); + repaint(); +} + void LfpChannelDisplayInfo::buttonClicked(Button* button) { diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h index d34bf7fc47f2e93aa559397c9786562770045cf2..caf4e5e51728ab879d457b0ba8fba1e2aebedd04 100755 --- a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h +++ b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h @@ -314,6 +314,7 @@ public: } channelType getType(); + void updateType(); bool fullredraw; // used to indicate that a full redraw is required. is set false after each full redraw @@ -361,6 +362,7 @@ public: void resized(); void setEnabledState(bool); + void updateType(); private: