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: