diff --git a/Resources/Bitfiles/rhd2000_1.41.bit b/Resources/Bitfiles/rhd2000_1.41.bit
new file mode 100644
index 0000000000000000000000000000000000000000..b1e354d4bfd2c8525341d03d9ff13aaf3d3f14d9
Binary files /dev/null and b/Resources/Bitfiles/rhd2000_1.41.bit differ
diff --git a/Source/Processors/DataThreads/RHD2000Editor.cpp b/Source/Processors/DataThreads/RHD2000Editor.cpp
index b2c3fea9d80b0b74b06c037976b4d81b0e91b643..a5b9321846b374749050a672f87fe34f7f0402a3 100644
--- a/Source/Processors/DataThreads/RHD2000Editor.cpp
+++ b/Source/Processors/DataThreads/RHD2000Editor.cpp
@@ -1199,7 +1199,7 @@ void HeadstageOptionsInterface::checkEnabledState()
 
     if (board->isHeadstageEnabled(hsNumber1))
     {
-        channelsOnHs1 = 32;
+		channelsOnHs1 = board->getChannelsInHeadstage(hsNumber1);
         hsButton1->setLabel(String(channelsOnHs1));
         hsButton1->setEnabledState(true);
     }
@@ -1212,7 +1212,7 @@ void HeadstageOptionsInterface::checkEnabledState()
 
     if (board->isHeadstageEnabled(hsNumber2))
     {
-        channelsOnHs2 = 32;
+        channelsOnHs2 = board->getChannelsInHeadstage(hsNumber2);
         hsButton2->setLabel(String(channelsOnHs2));
         hsButton2->setEnabledState(true);
     }
@@ -1230,11 +1230,11 @@ void HeadstageOptionsInterface::checkEnabledState()
 void HeadstageOptionsInterface::buttonClicked(Button* button)
 {
 
-    if (!(editor->acquisitionIsActive) && board->foundInputSource())
+   if (!(editor->acquisitionIsActive) && board->foundInputSource())
     {
 
         //std::cout << "Acquisition is not active" << std::endl;
-        if (button == hsButton1)
+		if ((button == hsButton1) && (board->getChannelsInHeadstage(hsNumber1)))
         {
             if (channelsOnHs1 == 32)
                 channelsOnHs1 = 16;
@@ -1246,11 +1246,11 @@ void HeadstageOptionsInterface::buttonClicked(Button* button)
             hsButton1->setLabel(String(channelsOnHs1));
             board->setNumChannels(hsNumber1, channelsOnHs1);
 
-           // board->updateChannelNames();
+            board->updateChannelNames();
             editor->updateSettings();
 
         }
-        else if (button == hsButton2)
+		else if ((button == hsButton2) && (board->getChannelsInHeadstage(hsNumber2)))
         {
             if (channelsOnHs2 == 32)
                 channelsOnHs2 = 16;
@@ -1259,7 +1259,7 @@ void HeadstageOptionsInterface::buttonClicked(Button* button)
 
             hsButton2->setLabel(String(channelsOnHs2));
             board->setNumChannels(hsNumber2, channelsOnHs2);
-         //   board->updateChannelNames();
+            board->updateChannelNames();
             editor->updateSettings();
         }
 
diff --git a/Source/Processors/DataThreads/RHD2000Thread.cpp b/Source/Processors/DataThreads/RHD2000Thread.cpp
index 6a6fb639228eaafb1caa84b3fab3518a3db8ca45..bbc9ecaae67fe82c7bd185aba427f0341c0f7050 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.cpp
+++ b/Source/Processors/DataThreads/RHD2000Thread.cpp
@@ -81,6 +81,10 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
     cableLengthPortA(0.914f), cableLengthPortB(0.914f), cableLengthPortC(0.914f), cableLengthPortD(0.914f), // default is 3 feet (0.914 m),
     audioOutputL(-1), audioOutputR(-1) ,numberingScheme(1)
 {
+
+	for (int i=0; i < MAX_NUM_HEADSTAGES; i++)
+		headstagesArray.add(new RHDHeadstage(static_cast<Rhd2000EvalBoard::BoardDataSource>(i)));
+
     evalBoard = new Rhd2000EvalBoard;
     dataBlock = new Rhd2000DataBlock(1);
     dataBuffer = new DataBuffer(2, 10000); // start with 2 channels and automatically resize
@@ -135,9 +139,11 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
             dacChannelsToUpdate[k] = true;
             dacStream[k] = 0;
             setDACthreshold(k, 65534);
+			dacChannels[k] = -1;
+			dacThresholds[k] = 0;
         }
 
-        evalBoard->getDacInformation(dacChannels,dacThresholds);
+       // evalBoard->getDacInformation(dacChannels,dacThresholds);
 
 		//sn->setDefaultNamingScheme(numberingScheme);
         //setDefaultChannelNamesAndType();
@@ -189,17 +195,18 @@ void RHD2000Thread::setDACchannel(int dacOutput, int stream, int channel)
     dacStream[dacOutput] = stream;
     dacChannelsToUpdate[dacOutput] = true;
     dacOutputShouldChange = true;
-	evalBoard->updateDacAssignment(dacOutput, stream,channel); // doesn't really change anything, but keep things in sync...
+   // evalBoard->updateDacAssignment(dacOutput, channel); // doesn't really change anything, but keep things in sync...
 }
 
 Array<int> RHD2000Thread::getDACchannels()
 {
-    Array<int> dacChannels;
+    Array<int> dacChannelsArray;
+	//dacChannelsArray.addArray(dacChannels,8);
     for (int k=0; k<8; k++)
-    {
-        dacChannels.add(evalBoard->gecDacDataChannel(k));
+	{
+        dacChannelsArray.add(dacChannels[k]);
     }
-    return dacChannels;
+    return dacChannelsArray;
 
 }
 bool RHD2000Thread::openBoard(String pathToLibrary)
@@ -346,6 +353,12 @@ void RHD2000Thread::initializeBoard()
     //  - clears the ttlOut
     //  - disables all DACs and sets gain to 0
 
+	setSampleRate(Rhd2000EvalBoard::SampleRate30000Hz);
+	evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortA, cableLengthPortA);
+    evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortB, cableLengthPortB);
+    evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortC, cableLengthPortC);
+    evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortD, cableLengthPortD);
+
     // Select RAM Bank 0 for AuxCmd3 initially, so the ADC is calibrated.
     evalBoard->selectAuxCommandBank(Rhd2000EvalBoard::PortA, Rhd2000EvalBoard::AuxCmd3, 0);
     evalBoard->selectAuxCommandBank(Rhd2000EvalBoard::PortB, Rhd2000EvalBoard::AuxCmd3, 0);
@@ -368,10 +381,10 @@ void RHD2000Thread::initializeBoard()
 
     // Read the resulting single data block from the USB interface. We don't
     // need to do anything with this, since it was only used for ADC calibration
-    Rhd2000DataBlock* dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams());
+    ScopedPointer<Rhd2000DataBlock> dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams());
 
 
-    // evalBoard->readDataBlock(dataBlock);
+     evalBoard->readDataBlock(dataBlock);
 
     // Now that ADC calibration has been performed, we switch to the command sequence
     // that does not execute ADC calibration.
@@ -385,9 +398,9 @@ void RHD2000Thread::initializeBoard()
                                     fastSettleEnabled ? 2 : 1);
 
 
-    updateRegisters();
+    //updateRegisters();
 
-    // Let's turn one LED on to indicate that the board is now connected
+   // Let's turn one LED on to indicate that the board is now connected
     int ledArray[8] = {1, 0, 0, 0, 0, 0, 0, 0};
     evalBoard->setLedDisplay(ledArray);
 
@@ -399,9 +412,13 @@ void RHD2000Thread::scanPorts()
     {
         return;
     }
+
+	//Clear previous known streams
+	enabledStreams.clear();
+
     // Scan SPI ports
 
-    int delay, stream, id;
+    int delay, hs, id;
 	int register59Value;
     //int numChannelsOnPort[4] = {0, 0, 0, 0};
     Rhd2000EvalBoard::BoardDataSource initStreamPorts[8] =
@@ -429,8 +446,9 @@ void RHD2000Thread::scanPorts()
     };
 
     chipId.insertMultiple(0,-1,8);
+	Array<int> tmpChipId(chipId);
 
-    setSampleRate(16, true); // set to 30 kHz temporarily
+	setSampleRate(Rhd2000EvalBoard::SampleRate30000Hz, true); // set to 30 kHz temporarily
 
     // Enable all data streams, and set sources to cover one or two chips
     // on Ports A-D.
@@ -508,28 +526,28 @@ void RHD2000Thread::scanPorts()
 
         // Read the Intan chip ID number from each RHD2000 chip found.
         // Record delay settings that yield good communication with the chip.
-        for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)//MAX_NUM_DATA_STREAMS; ++stream)
+        for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)//MAX_NUM_DATA_STREAMS; ++stream)
         {
             // std::cout << "Stream number " << stream << ", delay = " << delay << std::endl;
 
-			id = deviceId(dataBlock, stream, register59Value);
+			id = deviceId(dataBlock, hs, register59Value);
 
-            if (id == CHIP_ID_RHD2132 || id == CHIP_ID_RHD2216 ||
+			if (id == CHIP_ID_RHD2132 || id == CHIP_ID_RHD2216 ||
                 (id == CHIP_ID_RHD2164 && register59Value == REGISTER_59_MISO_A))
             {
                 //  std::cout << "Device ID found: " << id << std::endl;
 
-                sumGoodDelays.set(stream,sumGoodDelays[stream] + 1);
+                sumGoodDelays.set(hs,sumGoodDelays[hs] + 1);
 
-                if (indexFirstGoodDelay[stream] == -1)
+                if (indexFirstGoodDelay[hs] == -1)
                 {
-                    indexFirstGoodDelay.set(stream, delay);
-                    chipId.set(stream,id);
+                    indexFirstGoodDelay.set(hs, delay);
+                    tmpChipId.set(hs,id);
                 }
-                else if (indexSecondGoodDelay[stream] == -1)
+                else if (indexSecondGoodDelay[hs] == -1)
                 {
-                    indexSecondGoodDelay.set(stream,delay);
-                    chipId.set(stream,id);
+                    indexSecondGoodDelay.set(hs,delay);
+                    tmpChipId.set(hs,id);
                 }
             }
         }
@@ -545,7 +563,7 @@ void RHD2000Thread::scanPorts()
 #if DEBUG_EMULATE_HEADSTAGES > 0
 	for (int nd = 0; nd < MAX_NUM_DATA_STREAMS; ++nd)
 	{
-		if ((nd < DEBUG_EMULATE_HEADSTAGES) &&(chipId[0] > 0))
+		if ((nd < DEBUG_EMULATE_HEADSTAGES) &&(tmpChipId[0] > 0))
 		{
 			evalBoard->setDataSource(nd,initStreamPorts[0]);
 			enableHeadstage(nd,true);
@@ -557,29 +575,36 @@ void RHD2000Thread::scanPorts()
 	}
 #else
 	// Now, disable data streams where we did not find chips present.
-    for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
+	int chipIdx = 0;
+	for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)
     {
-        if (chipId[stream] > 0)
+		if ((tmpChipId[hs] > 0) && (enabledStreams.size() < MAX_NUM_DATA_STREAMS))
         {
+			chipId.set(chipIdx++,tmpChipId[hs]);
             //std::cout << "Enabling headstage on stream " << stream << std::endl;
-            if (chipId[stream] == CHIP_ID_RHD2164) //RHD2164
+            if (tmpChipId[hs] == CHIP_ID_RHD2164) //RHD2164
             {
-                //We just add it like a second headstage, allowing only one RHD2164 per channel
-                //This would need to change
-                evalBoard->setDataSource(stream+1,initStreamDdrPorts[stream]);
-                enableHeadstage(stream,true);
-                enableHeadstage(stream+1,true);
-                chipId.set(stream+1,CHIP_ID_RHD2164_B);
-                stream++;
+				if (enabledStreams.size() < MAX_NUM_DATA_STREAMS - 1)
+				{
+					enableHeadstage(hs,true,2,32);
+					chipId.set(chipIdx++,CHIP_ID_RHD2164_B);
+				}
+				else //just one stream left
+				{
+					enableHeadstage(hs,true,1,32);
+				}
             }
             else
-                enableHeadstage(stream, true);
+			{
+                enableHeadstage(hs, true,1,tmpChipId[hs] == 1 ? 32:16);
+			}
         }
         else
         {
-            enableHeadstage(stream, false);
+            enableHeadstage(hs, false);
         }
     }
+	updateBoardStreams();
 #endif
 
 
@@ -591,15 +616,15 @@ void RHD2000Thread::scanPorts()
     Array<int> optimumDelay;
     optimumDelay.insertMultiple(0,0,8);
 
-    for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
+	for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)
     {
-        if (sumGoodDelays[stream] == 1 || sumGoodDelays[stream] == 2)
+        if (sumGoodDelays[hs] == 1 || sumGoodDelays[hs] == 2)
         {
-            optimumDelay.set(stream,indexFirstGoodDelay[stream]);
+            optimumDelay.set(hs,indexFirstGoodDelay[hs]);
         }
-        else if (sumGoodDelays[stream] > 2)
+        else if (sumGoodDelays[hs] > 2)
         {
-            optimumDelay.set(stream,indexSecondGoodDelay[stream]);
+            optimumDelay.set(hs,indexSecondGoodDelay[hs]);
         }
     }
 
@@ -622,39 +647,33 @@ void RHD2000Thread::scanPorts()
         evalBoard->estimateCableLengthMeters(max(optimumDelay[6],optimumDelay[7]));
 
     setSampleRate(savedSampleRateIndex); // restore saved sample rate
-
-    updateRegisters();
+    //updateRegisters();
 }
 
 int RHD2000Thread::deviceId(Rhd2000DataBlock* dataBlock, int stream, int &register59Value)
 {
     bool intanChipPresent;
 
-    // First, check ROM registers 32-36 to verify that they hold 'INTAN'.
+    // First, check ROM registers 32-36 to verify that they hold 'INTAN', and
+    // the initial chip name ROM registers 24-26 that hold 'RHD'.
     // This is just used to verify that we are getting good data over the SPI
     // communication channel.
-    // std::cout << dataBlock->auxiliaryData[stream][2][32] << " ";
-    // std::cout << dataBlock->auxiliaryData[stream][2][33] << " ";
-    // std::cout << dataBlock->auxiliaryData[stream][2][34] << " ";
-    // std::cout << dataBlock->auxiliaryData[stream][2][35] << " ";
-    // std::cout << dataBlock->auxiliaryData[stream][2][36] << std::endl;
-
-    intanChipPresent = (dataBlock->auxiliaryData[stream][2][32] == 73 && // I = 73
-                        dataBlock->auxiliaryData[stream][2][33] == 78 && // N = 78
-                        dataBlock->auxiliaryData[stream][2][34] == 84 && // T = 84
-                        dataBlock->auxiliaryData[stream][2][35] == 65 && // A = 65
-                        dataBlock->auxiliaryData[stream][2][36] == 78);  // N = 78
-
-    // If the SPI communication is bad, return -1.  Otherwise, return the Intan
+    intanChipPresent = ((char) dataBlock->auxiliaryData[stream][2][32] == 'I' &&
+                        (char) dataBlock->auxiliaryData[stream][2][33] == 'N' &&
+                        (char) dataBlock->auxiliaryData[stream][2][34] == 'T' &&
+                        (char) dataBlock->auxiliaryData[stream][2][35] == 'A' &&
+                        (char) dataBlock->auxiliaryData[stream][2][36] == 'N' &&
+                        (char) dataBlock->auxiliaryData[stream][2][24] == 'R' &&
+                        (char) dataBlock->auxiliaryData[stream][2][25] == 'H' &&
+                        (char) dataBlock->auxiliaryData[stream][2][26] == 'D');
+
+	// If the SPI communication is bad, return -1.  Otherwise, return the Intan
     // chip ID number stored in ROM regstier 63.
-    if (!intanChipPresent)
-    {
-		register59Value = -1;
+    if (!intanChipPresent) {
+        register59Value = -1;
         return -1;
-    }
-    else
-    {
-		register59Value = dataBlock->auxiliaryData[stream][2][23]; // Register 59
+    } else {
+        register59Value = dataBlock->auxiliaryData[stream][2][23]; // Register 59
         return dataBlock->auxiliaryData[stream][2][19]; // chip ID (Register 63)
     }
 }
@@ -668,8 +687,19 @@ bool RHD2000Thread::isAcquisitionActive()
 
 void RHD2000Thread::setNumChannels(int hsNum, int numChannels)
 {
-    if (numChannelsPerDataStream[hsNum] > 0)
-        numChannelsPerDataStream.set(hsNum, numChannels);
+	if (headstagesArray[hsNum]->getNumChannels() == 32)
+	{
+		if (numChannels < headstagesArray[hsNum]->getNumChannels())
+			headstagesArray[hsNum]->setHalfChannels(true);
+		else
+			headstagesArray[hsNum]->setHalfChannels(false);
+		numChannelsPerDataStream.set(hsNum, numChannels);
+	}
+}
+
+int RHD2000Thread::getHeadstageChannels(int hsNum)
+{
+	return headstagesArray[hsNum]->getNumChannels();
 }
 
 
@@ -833,11 +863,11 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
     stream_prefix.add("D1");
     stream_prefix.add("D2");
 
-    for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+    for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
     {
-        if (numChannelsPerDataStream[i] > 0)
+		if (headstagesArray[i]->isPlugged())
         {
-            for (int k = 0; k < numChannelsPerDataStream[i]; k++)
+			for (int k = 0; k < headstagesArray[i]->getNumChannels(); k++)
             {
                 type.add(HEADSTAGE_CHANNEL);
 
@@ -864,16 +894,16 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
         }
     }
 	//Aux channels
-	for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+	for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
     {	
-    	if (numChannelsPerDataStream[i] > 0)
+    	if (headstagesArray[i]->isPlugged())
         {
 			for (int k = 0; k < 3; k++)
 		        {
 
 		            type.add(AUX_CHANNEL);
 
-		            if (channelModified(AUX_CHANNEL,i,numChannelsPerDataStream[i]+k, oldName,oldGain, dummy))
+		            if (channelModified(AUX_CHANNEL,i,headstagesArray[i]->getNumChannels()+k, oldName,oldGain, dummy))
 		            {
 		                Names.add(oldName);
 		                gains.add(oldGain);
@@ -892,7 +922,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
 		            }
 
 		            stream.add(i);
-		            originalChannelNumber.add(numChannelsPerDataStream[i]+k);
+		            originalChannelNumber.add(headstagesArray[i]->getNumChannels()+k);
 		        }
 		 }
 	}
@@ -905,7 +935,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
             channelNumber++;
             type.add(ADC_CHANNEL);
 
-			if (channelModified(ADC_CHANNEL,MAX_NUM_DATA_STREAMS,k, oldName,oldGain,dummy))
+			if (channelModified(ADC_CHANNEL,MAX_NUM_HEADSTAGES,k, oldName,oldGain,dummy))
             {
                 Names.add(oldName);
                 gains.add(oldGain);
@@ -916,7 +946,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
                 gains.add(getAdcBitVolts(k));
             }
             
-            stream.add(MAX_NUM_DATA_STREAMS);
+            stream.add(MAX_NUM_HEADSTAGES);
             originalChannelNumber.add(k);
 
         }
@@ -932,12 +962,12 @@ int RHD2000Thread::getNumChannels()
 int RHD2000Thread::getNumHeadstageOutputs()
 {
     numChannels = 0;
-    for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+	for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
     {
 
-        if (numChannelsPerDataStream[i] > 0)
+		if (headstagesArray[i]->isPlugged())
         {
-            numChannels += numChannelsPerDataStream[i];
+			numChannels += headstagesArray[i]->getNumActiveChannels();
         }
     }
 
@@ -951,9 +981,9 @@ int RHD2000Thread::getNumAuxOutputs()
 {
     int numAuxOutputs = 0;
 
-    for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+	for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
     {
-        if (numChannelsPerDataStream[i] > 0)
+        if (headstagesArray[i]->isPlugged() > 0)
         {
             numAuxOutputs += 3;
         }
@@ -1086,45 +1116,82 @@ bool RHD2000Thread::foundInputSource()
 
 }
 
-bool RHD2000Thread::enableHeadstage(int hsNum, bool enabled)
+bool RHD2000Thread::enableHeadstage(int hsNum, bool enabled, int nStr, int strChans)
 {
 
-    evalBoard->enableDataStream(hsNum, enabled);
+ /*   evalBoard->enableDataStream(hsNum, enabled);*/
 
-    if (enabled)
-    {
-        numChannelsPerDataStream.set(hsNum, 32);
-    }
-    else
-    {
-        numChannelsPerDataStream.set(hsNum, 0);
-    }
+	if (enabled)
+	{
+		headstagesArray[hsNum]->setNumStreams(nStr);
+		headstagesArray[hsNum]->setChannelsPerStream(strChans);
+		enabledStreams.add(headstagesArray[hsNum]->getDataStream(0));
+		numChannelsPerDataStream.add(strChans);
+		if (nStr > 1)
+		{
+			enabledStreams.add(headstagesArray[hsNum]->getDataStream(1));
+			numChannelsPerDataStream.add(strChans);
+		}
+	}
+	else
+	{
+		int idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(0));
+		if (idx >= 0)
+		{
+			enabledStreams.remove(idx);
+			numChannelsPerDataStream.remove(idx);
+		}
+		if (headstagesArray[hsNum]->getNumStreams() > 1)
+		{
+			idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(1));
+			if (idx >= 0)
+			{
+				enabledStreams.remove(idx);
+				numChannelsPerDataStream.remove(idx);
+			}
+		}
+		headstagesArray[hsNum]->setNumStreams(0);
+	}
 
-    std::cout << "Enabled channels: ";
+	/*    
+	std::cout << "Enabled channels: ";
 
     for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
     {
         std::cout << numChannelsPerDataStream[i] << " ";
-    }
-
-    std:: cout << std::endl;
+    }*/
 
+	dataBuffer->resize(getNumChannels(), 10000);
 
-    dataBuffer->resize(getNumChannels(), 10000);
+	return true;
+}
 
-    return true;
+void RHD2000Thread::updateBoardStreams()
+{
+	for (int i=0; i <  MAX_NUM_DATA_STREAMS; i++)
+	{
+		if (i < enabledStreams.size())
+		{
+			evalBoard->enableDataStream(i,true);
+			evalBoard->setDataSource(i,enabledStreams[i]);
+		}
+		else
+		{
+			evalBoard->enableDataStream(i,false);
+		}
+	}
 }
 
 bool RHD2000Thread::isHeadstageEnabled(int hsNum)
 {
 
-    if (numChannelsPerDataStream[hsNum] > 0)
-    {
-        return true;
-    }
+	return headstagesArray[hsNum]->isPlugged();
 
-    return false;
+}
 
+int RHD2000Thread::getChannelsInHeadstage(int hsNum)
+{
+	return headstagesArray[hsNum]->getNumChannels();
 }
 
 void RHD2000Thread::assignAudioOut(int dacChannel, int dataChannel)
@@ -1277,6 +1344,8 @@ void RHD2000Thread::setSampleRate(int sampleRateIndex, bool isTemporary)
     evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortC, cableLengthPortC);
     evalBoard->setCableLengthMeters(Rhd2000EvalBoard::PortD, cableLengthPortD);
 
+	updateRegisters();
+
 }
 
 void RHD2000Thread::updateRegisters()
@@ -1294,10 +1363,12 @@ void RHD2000Thread::updateRegisters()
     int commandSequenceLength;
     vector<int> commandList;
 
-    // Create a command list for the AuxCmd1 slot.  This command sequence will create a 250 Hz,
-    // zero-amplitude sine wave (i.e., a flatline).  We will change this when we want to perform
-    // impedance testing.
-    commandSequenceLength = chipRegisters.createCommandListZcheckDac(commandList, 250.0, 0.0);
+    // Create a command list for the AuxCmd1 slot.  This command sequence will continuously
+    // update Register 3, which controls the auxiliary digital output pin on each RHD2000 chip.
+    // In concert with the v1.4 Rhythm FPGA code, this permits real-time control of the digital
+    // output pin on chips on each SPI port.
+    chipRegisters.setDigOutLow();   // Take auxiliary output out of HiZ mode.
+    commandSequenceLength = chipRegisters.createCommandListUpdateDigOut(commandList);
     evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd1, 0);
     evalBoard->selectAuxCommandLength(Rhd2000EvalBoard::AuxCmd1, 0, commandSequenceLength - 1);
     evalBoard->selectAuxCommandBank(Rhd2000EvalBoard::PortA, Rhd2000EvalBoard::AuxCmd1, 0);
@@ -1490,82 +1561,74 @@ bool RHD2000Thread::updateBuffer()
 
         for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++)
         {
-            int streamNumber = -1;
             int channel = -1;
 
             // do the neural data channels first
-            for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
-            {
-                if (numChannelsPerDataStream[dataStream] > 0)
-                {
-                    streamNumber++;
+			for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++)
+			{
 
-                    for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++)
-                    {
+				for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++)
+				{
 
-                        //  std::cout << "reading sample stream " << streamNumber << " chan " << chan << " sample "<< samp << std::endl;
+					//  std::cout << "reading sample stream " << streamNumber << " chan " << chan << " sample "<< samp << std::endl;
 
-                        channel++;
+					channel++;
 
-                        int value = dataBlock->amplifierData[streamNumber][chan][samp];
+					int value = dataBlock->amplifierData[dataStream][chan][samp];
 
-                        thisSample[channel] = float(value-32768)*0.195f;
-                    }
+					thisSample[channel] = float(value-32768)*0.195f;
+				}
 
-                }
 
-            }
+			}
 
-            streamNumber = -1;
 
             // then do the Intan AUX channels
-            for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
+			for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++)
             {
-                if (numChannelsPerDataStream[dataStream] > 0)
-                {
-                    streamNumber++;
+				if (chipId[dataStream] != CHIP_ID_RHD2164_B) //Channel B of 2164 shouldn't be copied
+				{
+					if (samp % 4 == 1)   // every 4th sample should have auxiliary input data
+					{
 
-                    if (samp % 4 == 1)   // every 4th sample should have auxiliary input data
-                    {
+						// std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
 
-                        // std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
+						channel++;
+						thisSample[channel] = 0.0374 *
+							float(dataBlock->auxiliaryData[dataStream][1][samp + 0] - 45000.0f);
+						// constant offset keeps the values visible in the LFP Viewer
 
-                        channel++;
-                        thisSample[channel] = 0.0374 *
-                                              float(dataBlock->auxiliaryData[streamNumber][1][samp+0] - 45000.0f) ;
-                        // constant offset keeps the values visible in the LFP Viewer
+						auxBuffer[channel] = thisSample[channel];
 
-                        auxBuffer[channel] = thisSample[channel];
+						channel++;
+						thisSample[channel] = 0.0374 *
+							float(dataBlock->auxiliaryData[dataStream][1][samp + 1] - 45000.0f);
+						// constant offset keeps the values visible in the LFP Viewer
 
-                        channel++;
-                        thisSample[channel] = 0.0374 *
-                                              float(dataBlock->auxiliaryData[streamNumber][1][samp+1] - 45000.0f) ;
-                        // constant offset keeps the values visible in the LFP Viewer
+						auxBuffer[channel] = thisSample[channel];
 
-                        auxBuffer[channel] = thisSample[channel];
 
+						channel++;
+						thisSample[channel] = 0.0374 *
+							float(dataBlock->auxiliaryData[dataStream][1][samp + 2] - 45000.0f);
+						// constant offset keeps the values visible in the LFP Viewer
 
-                        channel++;
-                        thisSample[channel] = 0.0374 *
-                                              float(dataBlock->auxiliaryData[streamNumber][1][samp+2] - 45000.0f) ;
-                        // constant offset keeps the values visible in the LFP Viewer
+						auxBuffer[channel] = thisSample[channel];
 
-                        auxBuffer[channel] = thisSample[channel];
+					}
+					else    // repeat last values from buffer
+					{
 
-                    }
-                    else    // repeat last values from buffer
-                    {
+						//std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
 
-                        //std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
-
-                        channel++;
-                        thisSample[channel] = auxBuffer[channel];
-                        channel++;
-                        thisSample[channel] = auxBuffer[channel];
-                        channel++;
-                        thisSample[channel] = auxBuffer[channel];
-                    }
-                }
+						channel++;
+						thisSample[channel] = auxBuffer[channel];
+						channel++;
+						thisSample[channel] = auxBuffer[channel];
+						channel++;
+						thisSample[channel] = auxBuffer[channel];
+					}
+				}
 
             }
 
@@ -1607,7 +1670,8 @@ bool RHD2000Thread::updateBuffer()
                     evalBoard->enableDac(k, true);
                     evalBoard->selectDacDataStream(k, dacStream[k]);
                     evalBoard->selectDacDataChannel(k, dacChannels[k]);
-                    evalBoard->setDacThresholdVoltage(k, (int) dacThresholds[k]);
+					evalBoard->setDacThreshold(k, (int)abs((dacThresholds[k]/0.195) + 32768),dacThresholds[k] >= 0);
+                   // evalBoard->setDacThresholdVoltage(k, (int) dacThresholds[k]);
                 }
                 else
                 {
@@ -1617,8 +1681,8 @@ bool RHD2000Thread::updateBuffer()
         }
 
         evalBoard->setTtlMode(ttlMode);
-        evalBoard->setFastSettleByTTL(fastTTLSettleEnabled);
-        evalBoard->setFastSettleByTTLchannel(fastSettleTTLChannel);
+		evalBoard->enableExternalFastSettle(fastTTLSettleEnabled);
+		evalBoard->setExternalFastSettleChannel(fastSettleTTLChannel);
         evalBoard->setDacHighpassFilter(desiredDAChpf);
         evalBoard->enableDacHighpassFilter(desiredDAChpfState);
 
@@ -1872,8 +1936,7 @@ void RHD2000Thread::runImpedanceTest(Array<int>& streams, Array<int>& channels,
     evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd1, 1);
     evalBoard->selectAuxCommandLength(Rhd2000EvalBoard::AuxCmd1,
                                       0, commandSequenceLength - 1);
-    bool fastSettleMode = evalBoard->getExternalFastSettle();
-    if (fastSettleMode)
+    if (fastTTLSettleEnabled)
     {
         evalBoard->enableExternalFastSettle(false);
     }
@@ -2118,8 +2181,59 @@ void RHD2000Thread::runImpedanceTest(Array<int>& streams, Array<int>& channels,
     evalBoard->selectAuxCommandBank(Rhd2000EvalBoard::PortD, Rhd2000EvalBoard::AuxCmd3,
                                     fastSettleEnabled ? 2 : 1);
 
-    if (fastSettleMode)
+    if (fastTTLSettleEnabled)
     {
         evalBoard->enableExternalFastSettle(true);
     }
 }
+
+
+RHDHeadstage::RHDHeadstage(Rhd2000EvalBoard::BoardDataSource stream) : 
+numStreams(0), channelsPerStream(32), dataStream(stream), halfChannels(false)
+{
+}
+
+RHDHeadstage::~RHDHeadstage()
+{
+}
+
+void RHDHeadstage::setNumStreams(int num)
+{
+	numStreams = num;
+}
+
+void RHDHeadstage::setChannelsPerStream(int nchan)
+{
+	channelsPerStream = nchan;
+}
+
+int RHDHeadstage::getNumChannels()
+{
+	return channelsPerStream*numStreams;
+}
+
+int RHDHeadstage::getNumStreams()
+{
+	return numStreams;
+}
+
+void RHDHeadstage::setHalfChannels(bool half)
+{
+	halfChannels = half;
+}
+
+int RHDHeadstage::getNumActiveChannels()
+{
+	return (int)(getNumChannels() / (halfChannels ? 2 : 1));
+}
+
+Rhd2000EvalBoard::BoardDataSource RHDHeadstage::getDataStream(int index)
+{
+	if (index < 0 || index > 1) index = 0;
+	return static_cast<Rhd2000EvalBoard::BoardDataSource>(dataStream+MAX_NUM_HEADSTAGES*index);
+}
+
+bool RHDHeadstage::isPlugged()
+{
+	return (numStreams > 0);
+}
\ No newline at end of file
diff --git a/Source/Processors/DataThreads/RHD2000Thread.h b/Source/Processors/DataThreads/RHD2000Thread.h
index 6eb6c031de3f59ef9346261b51a5ad3efed7e173..9a5bd3cf6109c122c74bb1664d5167c81423f2c9 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.h
+++ b/Source/Processors/DataThreads/RHD2000Thread.h
@@ -40,9 +40,10 @@
 #include "../GenericProcessor/GenericProcessor.h"
 
 #define MAX_NUM_DATA_STREAMS 8
+#define MAX_NUM_HEADSTAGES 8
 
 class SourceNode;
-
+class RHDHeadstage;
 /**
 
   Communicates with the RHD2000 Evaluation Board from Intan Technologies
@@ -68,12 +69,8 @@ public:
     float getBitVolts(Channel* chan);
     float getAdcBitVolts(int channelNum);
 
-    // for internal use:
-    bool isHeadstageEnabled(int hsNum);
-
-    bool enableHeadstage(int hsNum, bool enabled);
-    void setCableLength(int hsNum, float length);
-    void setNumChannels(int hsNum, int nChannels);
+	bool isHeadstageEnabled(int hsNum);
+	int getChannelsInHeadstage(int hsNum);
 
     void setSampleRate(int index, bool temporary = false);
 
@@ -120,8 +117,15 @@ public:
     void setDefaultNamingScheme(int scheme);
 
 	String getChannelName(ChannelType t, int str, int ch);
+	void setNumChannels(int hsNum, int nChannels);
+	int getHeadstageChannels(int hsNum);
 
 private:
+
+    bool enableHeadstage(int hsNum, bool enabled, int nStr = 1, int strChans = 32);
+	void updateBoardStreams();
+    void setCableLength(int hsNum, float length);
+
     void setDefaultChannelNamesAndType();
     bool channelModified(ChannelType t, int str, int k, String &oldName, float &oldGain, int &index);
 
@@ -130,7 +134,6 @@ private:
     Rhd2000DataBlock* dataBlock;
 
     std::vector<std::vector<std::vector<double>>> amplifierPreFilter;
-    Array<int> numChannelsPerDataStream;
     void factorOutParallelCapacitance(double &impedanceMagnitude, double &impedancePhase,
                                               double frequency, double parasiticCapacitance);
     void empiricalResistanceCorrection(double &impedanceMagnitude, double &impedancePhase,
@@ -188,6 +191,9 @@ private:
     float *dacThresholds;
     bool *dacChannelsToUpdate;
     Array<int> chipId;
+	OwnedArray<RHDHeadstage> headstagesArray;
+	Array<Rhd2000EvalBoard::BoardDataSource> enabledStreams;
+	Array<int> numChannelsPerDataStream;
 
     // used for data stream names...
     int numberingScheme ;
@@ -203,4 +209,25 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHD2000Thread);
 };
 
+class RHDHeadstage
+{
+public:
+	RHDHeadstage(Rhd2000EvalBoard::BoardDataSource stream);
+	~RHDHeadstage();
+	void setNumStreams(int num);
+	void setChannelsPerStream(int nchan);
+	int getNumChannels();
+	int getNumStreams();
+	void setHalfChannels(bool half); //mainly used for de 16ch rhd2132 board
+	int getNumActiveChannels();
+	Rhd2000EvalBoard::BoardDataSource getDataStream(int index);
+	bool isPlugged();
+private:
+	Rhd2000EvalBoard::BoardDataSource dataStream;
+	int numStreams;
+	int channelsPerStream;
+	bool halfChannels;
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHDHeadstage);
+};
+
 #endif  // __RHD2000THREAD_H_2C4CBD67__
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.cpp b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.cpp
index d22a4ba36a9b557c50e5843ce5514714d7f21493..030ae354444ed4cee688ae4129605c285bdb6bb1 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.cpp
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.cpp
@@ -3,9 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000DataBlock Class
-// Version 1.0 (14 January 2013)
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -42,19 +42,19 @@ Rhd2000DataBlock::Rhd2000DataBlock(int numDataStreams)
 }
 
 // Allocates memory for a 1-D array of integers.
-void Rhd2000DataBlock::allocateIntArray1D(vector<int>& array1D, int xSize)
+void Rhd2000DataBlock::allocateIntArray1D(vector<int> &array1D, int xSize)
 {
     array1D.resize(xSize);
 }
 
 // Allocates memory for a 1-D array of unsigned integers.
-void Rhd2000DataBlock::allocateUIntArray1D(vector<unsigned int>& array1D, int xSize)
+void Rhd2000DataBlock::allocateUIntArray1D(vector<unsigned int> &array1D, int xSize)
 {
     array1D.resize(xSize);
 }
 
 // Allocates memory for a 2-D array of integers.
-void Rhd2000DataBlock::allocateIntArray2D(vector<vector<int> >& array2D, int xSize, int ySize)
+void Rhd2000DataBlock::allocateIntArray2D(vector<vector<int> > & array2D, int xSize, int ySize)
 {
     int i;
 
@@ -64,17 +64,15 @@ void Rhd2000DataBlock::allocateIntArray2D(vector<vector<int> >& array2D, int xSi
 }
 
 // Allocates memory for a 3-D array of integers.
-void Rhd2000DataBlock::allocateIntArray3D(vector<vector<vector<int> > >& array3D, int xSize, int ySize, int zSize)
+void Rhd2000DataBlock::allocateIntArray3D(vector<vector<vector<int> > > &array3D, int xSize, int ySize, int zSize)
 {
     int i, j;
 
     array3D.resize(xSize);
-    for (i = 0; i < xSize; ++i)
-    {
+    for (i = 0; i < xSize; ++i) {
         array3D[i].resize(ySize);
 
-        for (j = 0; j < ySize; ++j)
-        {
+        for (j = 0; j < ySize; ++j) {
             array3D[i][j].resize(zSize);
         }
     }
@@ -144,31 +142,25 @@ void Rhd2000DataBlock::fillFromUsbBuffer(unsigned char usbBuffer[], int blockInd
     int index, t, channel, stream, i;
 
     index = blockIndex * 2 * calculateDataBlockSizeInWords(numDataStreams);
-    for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t)
-    {
-        if (!checkUsbHeader(usbBuffer, index))
-        {
-            //cerr << "Error in Rhd2000EvalBoard::readDataBlock: Incorrect header." << endl;
+    for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t) {
+        if (!checkUsbHeader(usbBuffer, index)) {
+        //    cerr << "Error in Rhd2000EvalBoard::readDataBlock: Incorrect header." << endl;
         }
         index += 8;
         timeStamp[t] = convertUsbTimeStamp(usbBuffer, index);
         index += 4;
 
         // Read auxiliary results
-        for (channel = 0; channel < 3; ++channel)
-        {
-            for (stream = 0; stream < numDataStreams; ++stream)
-            {
+        for (channel = 0; channel < 3; ++channel) {
+            for (stream = 0; stream < numDataStreams; ++stream) {
                 auxiliaryData[stream][channel][t] = convertUsbWord(usbBuffer, index);
                 index += 2;
             }
         }
 
         // Read amplifier channels
-        for (channel = 0; channel < 32; ++channel)
-        {
-            for (stream = 0; stream < numDataStreams; ++stream)
-            {
+        for (channel = 0; channel < 32; ++channel) {
+            for (stream = 0; stream < numDataStreams; ++stream) {
                 amplifierData[stream][channel][t] = convertUsbWord(usbBuffer, index);
                 index += 2;
             }
@@ -178,8 +170,7 @@ void Rhd2000DataBlock::fillFromUsbBuffer(unsigned char usbBuffer[], int blockInd
         index += 2 * numDataStreams;
 
         // Read from AD5662 ADCs
-        for (i = 0; i < 8; ++i)
-        {
+        for (i = 0; i < 8; ++i) {
             boardAdcData[i][t] = convertUsbWord(usbBuffer, index);
             index += 2;
         }
@@ -203,25 +194,24 @@ void Rhd2000DataBlock::print(int stream) const
     cout << "RHD 2000 Data Block contents:" << endl;
     cout << "  ROM contents:" << endl;
     cout << "    Chip Name: " <<
-         (char) auxiliaryData[stream][2][24] <<
-         (char) auxiliaryData[stream][2][25] <<
-         (char) auxiliaryData[stream][2][26] <<
-         (char) auxiliaryData[stream][2][27] <<
-         (char) auxiliaryData[stream][2][28] <<
-         (char) auxiliaryData[stream][2][29] <<
-         (char) auxiliaryData[stream][2][30] <<
-         (char) auxiliaryData[stream][2][31] << endl;
+           (char) auxiliaryData[stream][2][24] <<
+           (char) auxiliaryData[stream][2][25] <<
+           (char) auxiliaryData[stream][2][26] <<
+           (char) auxiliaryData[stream][2][27] <<
+           (char) auxiliaryData[stream][2][28] <<
+           (char) auxiliaryData[stream][2][29] <<
+           (char) auxiliaryData[stream][2][30] <<
+           (char) auxiliaryData[stream][2][31] << endl;
     cout << "    Company Name:" <<
-         (char) auxiliaryData[stream][2][32] <<
-         (char) auxiliaryData[stream][2][33] <<
-         (char) auxiliaryData[stream][2][34] <<
-         (char) auxiliaryData[stream][2][35] <<
-         (char) auxiliaryData[stream][2][36] << endl;
+           (char) auxiliaryData[stream][2][32] <<
+           (char) auxiliaryData[stream][2][33] <<
+           (char) auxiliaryData[stream][2][34] <<
+           (char) auxiliaryData[stream][2][35] <<
+           (char) auxiliaryData[stream][2][36] << endl;
     cout << "    Intan Chip ID: " << auxiliaryData[stream][2][19] << endl;
     cout << "    Number of Amps: " << auxiliaryData[stream][2][20] << endl;
     cout << "    Unipolar/Bipolar Amps: ";
-    switch (auxiliaryData[stream][2][21])
-    {
+    switch (auxiliaryData[stream][2][21]) {
         case 0:
             cout << "bipolar";
             break;
@@ -246,7 +236,7 @@ void Rhd2000DataBlock::print(int stream) const
     cout << "    MUX bias:              " << ((auxiliaryData[stream][2][RamOffset + 2] & 0x3f) >> 0) << endl;
     cout << "    MUX load:              " << ((auxiliaryData[stream][2][RamOffset + 3] & 0xe0) >> 5) << endl;
     cout << "    tempS2, tempS1:        " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x10) >> 4) << "," <<
-         ((auxiliaryData[stream][2][RamOffset + 3] & 0x08) >> 3) << endl;
+           ((auxiliaryData[stream][2][RamOffset + 3] & 0x08) >> 3) << endl;
     cout << "    tempen:                " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x04) >> 2) << endl;
     cout << "    digout HiZ:            " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x02) >> 1) << endl;
     cout << "    digout:                " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x01) >> 0) << endl;
@@ -285,45 +275,45 @@ void Rhd2000DataBlock::print(int stream) const
     cout << fixed << setprecision(2);
 
     cout << "    RH1 DAC1, DAC2:        " << rH1Dac1 << " " << rH1Dac2 << " = " << (rH1 / 1000) <<
-         " kOhm" << endl;
+            " kOhm" << endl;
     cout << "    RH2 DAC1, DAC2:        " << rH2Dac1 << " " << rH2Dac2 << " = " << (rH2 / 1000) <<
-         " kOhm" << endl;
+            " kOhm" << endl;
     cout << "    RL DAC1, DAC2, DAC3:   " << rLDac1 << " " << rLDac2 << " " << rLDac3 << " = " <<
-         (rL / 1000) << " kOhm" << endl;
+            (rL / 1000) << " kOhm" << endl;
 
     cout << "    amp power[31:0]:       " <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x80) >> 7) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x40) >> 6) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x20) >> 5) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x10) >> 4) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x08) >> 3) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x04) >> 2) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x02) >> 1) <<
-         ((auxiliaryData[stream][2][RamOffset + 17] & 0x01) >> 0) << " " <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x80) >> 7) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x40) >> 6) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x20) >> 5) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x10) >> 4) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x08) >> 3) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x04) >> 2) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x02) >> 1) <<
-         ((auxiliaryData[stream][2][RamOffset + 16] & 0x01) >> 0) << " " <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x80) >> 7) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x40) >> 6) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x20) >> 5) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x10) >> 4) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x08) >> 3) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x04) >> 2) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x02) >> 1) <<
-         ((auxiliaryData[stream][2][RamOffset + 15] & 0x01) >> 0) << " " <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x80) >> 7) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x40) >> 6) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x20) >> 5) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x10) >> 4) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x08) >> 3) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x04) >> 2) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x02) >> 1) <<
-         ((auxiliaryData[stream][2][RamOffset + 14] & 0x01) >> 0) << endl;
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x80) >> 7) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x40) >> 6) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x20) >> 5) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x10) >> 4) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x08) >> 3) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x04) >> 2) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x02) >> 1) <<
+           ((auxiliaryData[stream][2][RamOffset + 17] & 0x01) >> 0) << " " <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x80) >> 7) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x40) >> 6) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x20) >> 5) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x10) >> 4) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x08) >> 3) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x04) >> 2) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x02) >> 1) <<
+           ((auxiliaryData[stream][2][RamOffset + 16] & 0x01) >> 0) << " " <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x80) >> 7) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x40) >> 6) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x20) >> 5) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x10) >> 4) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x08) >> 3) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x04) >> 2) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x02) >> 1) <<
+           ((auxiliaryData[stream][2][RamOffset + 15] & 0x01) >> 0) << " " <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x80) >> 7) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x40) >> 6) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x20) >> 5) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x10) >> 4) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x08) >> 3) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x04) >> 2) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x02) >> 1) <<
+           ((auxiliaryData[stream][2][RamOffset + 14] & 0x01) >> 0) << endl;
 
     cout << endl;
 
@@ -338,7 +328,7 @@ void Rhd2000DataBlock::print(int stream) const
 
     cout << setprecision(1);
     cout << "  Temperature sensor (only one reading): " << tempUnitsC << " C (" <<
-         tempUnitsF << " F)" << endl;
+            tempUnitsF << " F)" << endl;
 
     cout << setprecision(2);
     cout << "  Supply voltage sensor                : " << vddSense << " V" << endl;
@@ -354,7 +344,7 @@ void Rhd2000DataBlock::print(int stream) const
 // the processor running the operating system.
 //
 // (See "Endianness" article in Wikipedia for more information.)
-void Rhd2000DataBlock::writeWordLittleEndian(ofstream& outputStream, int dataWord) const
+void Rhd2000DataBlock::writeWordLittleEndian(ofstream &outputStream, int dataWord) const
 {
     unsigned short msb, lsb;
 
@@ -366,29 +356,23 @@ void Rhd2000DataBlock::writeWordLittleEndian(ofstream& outputStream, int dataWor
 }
 
 // Write contents of data block to a binary output stream (saveOut) in little endian format.
-void Rhd2000DataBlock::write(ofstream& saveOut, int numDataStreams) const
+void Rhd2000DataBlock::write(ofstream &saveOut, int numDataStreams) const
 {
     int t, channel, stream, i;
 
-    for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t)
-    {
+    for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t) {
         writeWordLittleEndian(saveOut, timeStamp[t]);
-        for (channel = 0; channel < 32; ++channel)
-        {
-            for (stream = 0; stream < numDataStreams; ++stream)
-            {
+        for (channel = 0; channel < 32; ++channel) {
+            for (stream = 0; stream < numDataStreams; ++stream) {
                 writeWordLittleEndian(saveOut, amplifierData[stream][channel][t]);
             }
         }
-        for (channel = 0; channel < 3; ++channel)
-        {
-            for (stream = 0; stream < numDataStreams; ++stream)
-            {
+        for (channel = 0; channel < 3; ++channel) {
+            for (stream = 0; stream < numDataStreams; ++stream) {
                 writeWordLittleEndian(saveOut, auxiliaryData[stream][channel][t]);
             }
         }
-        for (i = 0; i < 8; ++i)
-        {
+        for (i = 0; i < 8; ++i) {
             writeWordLittleEndian(saveOut, boardAdcData[i][t]);
         }
         writeWordLittleEndian(saveOut, ttlIn[t]);
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h
index 121d43e92d9b67016f7009ef7350fb216eaec76a..4cf6705d5e95795ca0e53ca2c9e1754f1c1970b8 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h
@@ -3,8 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000DataBlock Class Header File
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -20,7 +21,7 @@
 #ifndef RHD2000DATABLOCK_H
 #define RHD2000DATABLOCK_H
 
-#define SAMPLES_PER_DATA_BLOCK 300
+#define SAMPLES_PER_DATA_BLOCK 300 //modified by Open-ephys
 #define RHD2000_HEADER_MAGIC_NUMBER 0xc691199927021942
 
 using namespace std;
@@ -43,15 +44,15 @@ public:
     static unsigned int getSamplesPerDataBlock();
     void fillFromUsbBuffer(unsigned char usbBuffer[], int blockIndex, int numDataStreams);
     void print(int stream) const;
-    void write(ofstream& saveOut, int numDataStreams) const;
+    void write(ofstream &saveOut, int numDataStreams) const;
 
 private:
-    void allocateIntArray3D(vector<vector<vector<int> > >& array3D, int xSize, int ySize, int zSize);
-    void allocateIntArray2D(vector<vector<int> >& array2D, int xSize, int ySize);
-    void allocateIntArray1D(vector<int>& array1D, int xSize);
-    void allocateUIntArray1D(vector<unsigned int>& array1D, int xSize);
+    void allocateIntArray3D(vector<vector<vector<int> > > &array3D, int xSize, int ySize, int zSize);
+    void allocateIntArray2D(vector<vector<int> > &array2D, int xSize, int ySize);
+    void allocateIntArray1D(vector<int> &array1D, int xSize);
+    void allocateUIntArray1D(vector<unsigned int> &array1D, int xSize);
 
-    void writeWordLittleEndian(ofstream& outputStream, int dataWord) const;
+    void writeWordLittleEndian(ofstream &outputStream, int dataWord) const;
 
     bool checkUsbHeader(unsigned char usbBuffer[], int index);
     unsigned int convertUsbTimeStamp(unsigned char usbBuffer[], int index);
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.cpp b/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.cpp
index 5d7452ca6e47647683b6d3b2715e28d8e1e6a9bd..4cf3735cacc3c5bffd3289f2e5c47c5b83f9a64b 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.cpp
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.cpp
@@ -3,9 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000EvalBoard Class
-// Version 1.0 (14 January 2013)
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -23,7 +23,7 @@
 #include <fstream>
 #include <vector>
 #include <queue>
-#include <math.h>
+#include <cmath>
 
 #include "rhd2000evalboard.h"
 #include "rhd2000datablock.h"
@@ -39,33 +39,21 @@ using namespace std;
 Rhd2000EvalBoard::Rhd2000EvalBoard()
 {
     int i;
-    fast_settle_enabled = false;
     sampleRate = SampleRate30000Hz; // Rhythm FPGA boots up with 30.0 kS/s/channel sampling rate
     numDataStreams = 0;
-    dev = 0; //nullptr;
+	dev = 0;
 
-    for (i = 0; i < MAX_NUM_DATA_STREAMS; ++i)
-    {
+    for (i = 0; i < MAX_NUM_DATA_STREAMS; ++i) {
         dataStreamEnabled[i] = 0;
     }
-    dacChannelAssignment = new int[8];
-	dacStreamAssignment = new int[8];
-    dacChannelThreshold = new float[8];
-    for (int k=0;k<8;k++)
-    {
-		dacStreamAssignment[k] = -1;
-        dacChannelAssignment[k] = -1;
-        dacChannelThreshold[k] =0;
-    }
+
+    cableDelay.resize(4, -1);
 }
 
-//Destructor: Deletes the device to avoid memory leak
+//Destructor: Deletes the device to avoid memory leak in Open ephys
 Rhd2000EvalBoard::~Rhd2000EvalBoard()
 {
     if (dev != 0) delete dev;
-	delete dacChannelAssignment;
-	delete dacChannelThreshold;
-	delete dacStreamAssignment;
 }
 
 // Find an Opal Kelly XEM6010-LX45 board attached to a USB port and open it.
@@ -76,47 +64,40 @@ int Rhd2000EvalBoard::open(const char* libname)
     string serialNumber = "";
     int i, nDevices;
 
-    cout << "---- Intan Technologies ---- Rhythm RHD2000 Controller v1.0 ----" << endl << endl;
-    if (okFrontPanelDLL_LoadLib(libname) == false)
-    {
+    cout << "---- Intan Technologies ---- Rhythm RHD2000 Controller v1.41 ----" << endl << endl;
+    if (okFrontPanelDLL_LoadLib(NULL) == false) {
         cerr << "FrontPanel DLL could not be loaded.  " <<
-             "Make sure this DLL is in the application start directory." << endl;
+                "Make sure this DLL is in the application start directory." << endl;
         return -1;
     }
     okFrontPanelDLL_GetVersion(dll_date, dll_time);
     cout << endl << "FrontPanel DLL loaded.  Built: " << dll_date << "  " << dll_time << endl;
 
-    if (dev != 0) delete dev; //Avoid memory leaks if open is called twice.
-
     dev = new okCFrontPanel;
 
     cout << endl << "Scanning USB for Opal Kelly devices..." << endl << endl;
     nDevices = dev->GetDeviceCount();
     cout << "Found " << nDevices << " Opal Kelly device" << ((nDevices == 1) ? "" : "s") <<
-         " connected:" << endl;
-    for (i = 0; i < nDevices; ++i)
-    {
+            " connected:" << endl;
+    for (i = 0; i < nDevices; ++i) {
         cout << "  Device #" << i + 1 << ": Opal Kelly " <<
-             opalKellyModelName(dev->GetDeviceListModel(i)).c_str() <<
-             " with serial number " << dev->GetDeviceListSerial(i).c_str() << endl;
+                opalKellyModelName(dev->GetDeviceListModel(i)).c_str() <<
+                " with serial number " << dev->GetDeviceListSerial(i).c_str() << endl;
     }
     cout << endl;
 
     // Find first device in list of type XEM6010LX45.
-    for (i = 0; i < nDevices; ++i)
-    {
-        if (dev->GetDeviceListModel(i) == OK_PRODUCT_XEM6010LX45)
-        {
+    for (i = 0; i < nDevices; ++i) {
+        if (dev->GetDeviceListModel(i) == OK_PRODUCT_XEM6010LX45) {
             serialNumber = dev->GetDeviceListSerial(i);
             break;
         }
     }
 
     // Attempt to open device.
-    if (dev->OpenBySerial(serialNumber) != okCFrontPanel::NoError)
-    {
+    if (dev->OpenBySerial(serialNumber) != okCFrontPanel::NoError) {
         delete dev;
-        dev = 0; //nullptr;
+		dev = 0;
         cerr << "Device could not be opened.  Is one connected?" << endl;
         return -2;
     }
@@ -127,7 +108,7 @@ int Rhd2000EvalBoard::open(const char* libname)
     // Get some general information about the XEM.
     cout << "FPGA system clock: " << getSystemClockFreq() << " MHz" << endl; // Should indicate 100 MHz
     cout << "Opal Kelly device firmware version: " << dev->GetDeviceMajorVersion() << "." <<
-         dev->GetDeviceMinorVersion() << endl;
+            dev->GetDeviceMinorVersion() << endl;
     cout << "Opal Kelly device serial number: " << dev->GetSerialNumber().c_str() << endl;
     cout << "Opal Kelly device ID string: " << dev->GetDeviceID().c_str() << endl << endl;
 
@@ -139,8 +120,7 @@ bool Rhd2000EvalBoard::uploadFpgaBitfile(string filename)
 {
     okCFrontPanel::ErrorCode errorCode = dev->ConfigureFPGA(filename);
 
-    switch (errorCode)
-    {
+    switch (errorCode) {
         case okCFrontPanel::NoError:
             break;
         case okCFrontPanel::DeviceNotOpen:
@@ -170,11 +150,10 @@ bool Rhd2000EvalBoard::uploadFpgaBitfile(string filename)
     }
 
     // Check for Opal Kelly FrontPanel support in the FPGA configuration.
-    if (dev->IsFrontPanelEnabled() == false)
-    {
+    if (dev->IsFrontPanelEnabled() == false) {
         cerr << "Opal Kelly FrontPanel support is not enabled in this FPGA configuration." << endl;
         delete dev;
-        dev = 0; //nullptr;
+		dev = 0;
         return(false);
     }
 
@@ -183,26 +162,17 @@ bool Rhd2000EvalBoard::uploadFpgaBitfile(string filename)
     boardId = dev->GetWireOutValue(WireOutBoardId);
     boardVersion = dev->GetWireOutValue(WireOutBoardVersion);
 
-    if (boardId != RHYTHM_BOARD_ID)
-    {
+    if (boardId != RHYTHM_BOARD_ID) {
         cerr << "FPGA configuration does not support Rhythm.  Incorrect board ID: " << boardId << endl;
         return(false);
-    }
-    else
-    {
+    } else {
         cout << "Rhythm configuration file successfully loaded.  Rhythm version number: " <<
-             boardVersion << endl << endl;
+                boardVersion << endl << endl;
     }
 
     return(true);
 }
 
-// Uses the Opal Kelly library to reset the FPGA
-void Rhd2000EvalBoard::resetFpga() 
-{
-    dev->ResetFPGA();
-}
-
 // Reads system clock frequency from Opal Kelly board (in MHz).  Should be 100 MHz for normal
 // Rhythm operation.
 double Rhd2000EvalBoard::getSystemClockFreq() const
@@ -256,8 +226,7 @@ void Rhd2000EvalBoard::initialize()
     setDataSource(7, PortD2);
 
     enableDataStream(0, true);        // start with only one data stream enabled
-    for (i = 1; i < MAX_NUM_DATA_STREAMS; i++)
-    {
+    for (i = 1; i < MAX_NUM_DATA_STREAMS; i++) {
         enableDataStream(i, false);
     }
 
@@ -288,14 +257,12 @@ void Rhd2000EvalBoard::initialize()
     selectDacDataChannel(6, 0);
     selectDacDataChannel(7, 0);
 
-    setDacManual(DacManual1, 32768);    // midrange value = 0 V
-    setDacManual(DacManual2, 32768);    // midrange value = 0 V
+    setDacManual(32768);    // midrange value = 0 V
 
     setDacGain(0);
     setAudioNoiseSuppress(0);
 
-    setTtlMode(0);          // If 1 then Digital outputs 0-7 are DAC comparators; 8-15 under manual control
-                            // by default, set to 0 (all are under manual control).
+    setTtlMode(1);          // Digital outputs 0-7 are DAC comparators; 8-15 under manual control
 
     setDacThreshold(0, 32768, true);
     setDacThreshold(1, 32768, true);
@@ -305,6 +272,18 @@ void Rhd2000EvalBoard::initialize()
     setDacThreshold(5, 32768, true);
     setDacThreshold(6, 32768, true);
     setDacThreshold(7, 32768, true);
+
+    enableExternalFastSettle(false);
+    setExternalFastSettleChannel(0);
+
+    enableExternalDigOut(PortA, false);
+    enableExternalDigOut(PortB, false);
+    enableExternalDigOut(PortC, false);
+    enableExternalDigOut(PortD, false);
+    setExternalDigOutChannel(PortA, 0);
+    setExternalDigOutChannel(PortB, 0);
+    setExternalDigOutChannel(PortC, 0);
+    setExternalDigOutChannel(PortD, 0);
 }
 
 // Set the per-channel sampling rate of the RHD2000 chips connected to the FPGA.
@@ -365,78 +344,77 @@ bool Rhd2000EvalBoard::setSampleRate(AmplifierSampleRate newSampleRate)
 
     unsigned long M, D;
 
-    switch (newSampleRate)
-    {
-        case SampleRate1000Hz:
-            M = 7;
-            D = 125;
-            break;
-        case SampleRate1250Hz:
-            M = 7;
-            D = 100;
-            break;
-        case SampleRate1500Hz:
-            M = 21;
-            D = 250;
-            break;
-        case SampleRate2000Hz:
-            M = 14;
-            D = 125;
-            break;
-        case SampleRate2500Hz:
-            M = 35;
-            D = 250;
-            break;
-        case SampleRate3000Hz:
-            M = 21;
-            D = 125;
-            break;
-        case SampleRate3333Hz:
-            M = 14;
-            D = 75;
-            break;
-        case SampleRate4000Hz:
-            M = 28;
-            D = 125;
-            break;
-        case SampleRate5000Hz:
-            M = 7;
-            D = 25;
-            break;
-        case SampleRate6250Hz:
-            M = 7;
-            D = 20;
-            break;
-        case SampleRate8000Hz:
-            M = 112;
-            D = 250;
-            break;
-        case SampleRate10000Hz:
-            M = 14;
-            D = 25;
-            break;
-        case SampleRate12500Hz:
-            M = 7;
-            D = 10;
-            break;
-        case SampleRate15000Hz:
-            M = 21;
-            D = 25;
-            break;
-        case SampleRate20000Hz:
-            M = 28;
-            D = 25;
-            break;
-        case SampleRate25000Hz:
-            M = 35;
-            D = 25;
-            break;
-        case SampleRate30000Hz:
-            M = 42;
-            D = 25;
-            break;
-        default:
-            return(false);
+    switch (newSampleRate) {
+    case SampleRate1000Hz:
+        M = 7;
+        D = 125;
+        break;
+    case SampleRate1250Hz:
+        M = 7;
+        D = 100;
+        break;
+    case SampleRate1500Hz:
+        M = 21;
+        D = 250;
+        break;
+    case SampleRate2000Hz:
+        M = 14;
+        D = 125;
+        break;
+    case SampleRate2500Hz:
+        M = 35;
+        D = 250;
+        break;
+    case SampleRate3000Hz:
+        M = 21;
+        D = 125;
+        break;
+    case SampleRate3333Hz:
+        M = 14;
+        D = 75;
+        break;
+    case SampleRate4000Hz:
+        M = 28;
+        D = 125;
+        break;
+    case SampleRate5000Hz:
+        M = 7;
+        D = 25;
+        break;
+    case SampleRate6250Hz:
+        M = 7;
+        D = 20;
+        break;
+    case SampleRate8000Hz:
+        M = 112;
+        D = 250;
+        break;
+    case SampleRate10000Hz:
+        M = 14;
+        D = 25;
+        break;
+    case SampleRate12500Hz:
+        M = 7;
+        D = 10;
+        break;
+    case SampleRate15000Hz:
+        M = 21;
+        D = 25;
+        break;
+    case SampleRate20000Hz:
+        M = 28;
+        D = 25;
+        break;
+    case SampleRate25000Hz:
+        M = 35;
+        D = 25;
+        break;
+    case SampleRate30000Hz:
+        M = 42;
+        D = 25;
+        break;
+    default:
+        return(false);
     }
 
     sampleRate = newSampleRate;
@@ -458,61 +436,60 @@ bool Rhd2000EvalBoard::setSampleRate(AmplifierSampleRate newSampleRate)
 // Returns the current per-channel sampling rate (in Hz) as a floating-point number.
 double Rhd2000EvalBoard::getSampleRate() const
 {
-    switch (sampleRate)
-    {
-        case SampleRate1000Hz:
-            return 1000.0;
-            break;
-        case SampleRate1250Hz:
-            return 1250.0;
-            break;
-        case SampleRate1500Hz:
-            return 1500.0;
-            break;
-        case SampleRate2000Hz:
-            return 2000.0;
-            break;
-        case SampleRate2500Hz:
-            return 2500.0;
-            break;
-        case SampleRate3000Hz:
-            return 3000.0;
-            break;
-        case SampleRate3333Hz:
-            return (10000.0 / 3.0);
-            break;
-        case SampleRate4000Hz:
-            return 4000.0;
-            break;
-        case SampleRate5000Hz:
-            return 5000.0;
-            break;
-        case SampleRate6250Hz:
-            return 6250.0;
-            break;
-        case SampleRate8000Hz:
-            return 8000.0;
-            break;
-        case SampleRate10000Hz:
-            return 10000.0;
-            break;
-        case SampleRate12500Hz:
-            return 12500.0;
-            break;
-        case SampleRate15000Hz:
-            return 15000.0;
-            break;
-        case SampleRate20000Hz:
-            return 20000.0;
-            break;
-        case SampleRate25000Hz:
-            return 25000.0;
-            break;
-        case SampleRate30000Hz:
-            return 30000.0;
-            break;
-        default:
-            return -1.0;
+    switch (sampleRate) {
+    case SampleRate1000Hz:
+        return 1000.0;
+        break;
+    case SampleRate1250Hz:
+        return 1250.0;
+        break;
+    case SampleRate1500Hz:
+        return 1500.0;
+        break;
+    case SampleRate2000Hz:
+        return 2000.0;
+        break;
+    case SampleRate2500Hz:
+        return 2500.0;
+        break;
+    case SampleRate3000Hz:
+        return 3000.0;
+        break;
+    case SampleRate3333Hz:
+        return (10000.0 / 3.0);
+        break;
+    case SampleRate4000Hz:
+        return 4000.0;
+        break;
+    case SampleRate5000Hz:
+        return 5000.0;
+        break;
+    case SampleRate6250Hz:
+        return 6250.0;
+        break;
+    case SampleRate8000Hz:
+        return 8000.0;
+        break;
+    case SampleRate10000Hz:
+        return 10000.0;
+        break;
+    case SampleRate12500Hz:
+        return 12500.0;
+        break;
+    case SampleRate15000Hz:
+        return 15000.0;
+        break;
+    case SampleRate20000Hz:
+        return 20000.0;
+        break;
+    case SampleRate25000Hz:
+        return 25000.0;
+        break;
+    case SampleRate30000Hz:
+        return 30000.0;
+        break;
+    default:
+        return -1.0;
     }
 }
 
@@ -528,41 +505,27 @@ void Rhd2000EvalBoard::printCommandList(const vector<int> &commandList) const
     int cmd, channel, reg, data;
 
     cout << endl;
-    for (i = 0; i < commandList.size(); ++i)
-    {
+    for (i = 0; i < commandList.size(); ++i) {
         cmd = commandList[i];
-        if (cmd < 0 || cmd > 0xffff)
-        {
+        if (cmd < 0 || cmd > 0xffff) {
             cout << "  command[" << i << "] = INVALID COMMAND: " << cmd << endl;
-        }
-        else if ((cmd & 0xc000) == 0x0000)
-        {
+        } else if ((cmd & 0xc000) == 0x0000) {
             channel = (cmd & 0x3f00) >> 8;
             cout << "  command[" << i << "] = CONVERT(" << channel << ")" << endl;
-        }
-        else if ((cmd & 0xc000) == 0xc000)
-        {
+        } else if ((cmd & 0xc000) == 0xc000) {
             reg = (cmd & 0x3f00) >> 8;
             cout << "  command[" << i << "] = READ(" << reg << ")" << endl;
-        }
-        else if ((cmd & 0xc000) == 0x8000)
-        {
+        } else if ((cmd & 0xc000) == 0x8000) {
             reg = (cmd & 0x3f00) >> 8;
             data = (cmd & 0x00ff);
             cout << "  command[" << i << "] = WRITE(" << reg << ",";
             cout << hex << uppercase << internal << setfill('0') << setw(2) << data << nouppercase << dec;
             cout << ")" << endl;
-        }
-        else if (cmd == 0x5500)
-        {
+        } else if (cmd == 0x5500) {
             cout << "  command[" << i << "] = CALIBRATE" << endl;
-        }
-        else if (cmd == 0x6a00)
-        {
+        } else if (cmd == 0x6a00) {
             cout << "  command[" << i << "] = CLEAR" << endl;
-        }
-        else
-        {
+        } else {
             cout << "  command[" << i << "] = INVALID COMMAND: ";
             cout << hex << uppercase << internal << setfill('0') << setw(4) << cmd << nouppercase << dec;
             cout << endl;
@@ -577,26 +540,22 @@ void Rhd2000EvalBoard::uploadCommandList(const vector<int> &commandList, AuxCmdS
 {
     unsigned int i;
 
-    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3)
-    {
+    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) {
         cerr << "Error in Rhd2000EvalBoard::uploadCommandList: auxCommandSlot out of range." << endl;
         return;
     }
 
-    if (bank < 0 || bank > 15)
-    {
+    if (bank < 0 || bank > 15) {
         cerr << "Error in Rhd2000EvalBoard::uploadCommandList: bank out of range." << endl;
         return;
     }
 
-    for (i = 0; i < commandList.size(); ++i)
-    {
+    for (i = 0; i < commandList.size(); ++i) {
         dev->SetWireInValue(WireInCmdRamData, commandList[i]);
         dev->SetWireInValue(WireInCmdRamAddr, i);
         dev->SetWireInValue(WireInCmdRamBank, bank);
         dev->UpdateWireIns();
-        switch (auxCommandSlot)
-        {
+        switch (auxCommandSlot) {
             case AuxCmd1:
                 dev->ActivateTriggerIn(TrigInRamWrite, 0);
                 break;
@@ -616,44 +575,40 @@ void Rhd2000EvalBoard::selectAuxCommandBank(BoardPort port, AuxCmdSlot auxComman
 {
     int bitShift;
 
-    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3)
-    {
+    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) {
         cerr << "Error in Rhd2000EvalBoard::selectAuxCommandBank: auxCommandSlot out of range." << endl;
         return;
     }
-    if (bank < 0 || bank > 15)
-    {
+    if (bank < 0 || bank > 15) {
         cerr << "Error in Rhd2000EvalBoard::selectAuxCommandBank: bank out of range." << endl;
         return;
     }
 
-    switch (port)
-    {
-        case PortA:
-            bitShift = 0;
-            break;
-        case PortB:
-            bitShift = 4;
-            break;
-        case PortC:
-            bitShift = 8;
-            break;
-        case PortD:
-            bitShift = 12;
-            break;
-    }
-
-    switch (auxCommandSlot)
-    {
-        case AuxCmd1:
-            dev->SetWireInValue(WireInAuxCmdBank1, bank << bitShift, 0x000f << bitShift);
-            break;
-        case AuxCmd2:
-            dev->SetWireInValue(WireInAuxCmdBank2, bank << bitShift, 0x000f << bitShift);
-            break;
-        case AuxCmd3:
-            dev->SetWireInValue(WireInAuxCmdBank3, bank << bitShift, 0x000f << bitShift);
-            break;
+    switch (port) {
+    case PortA:
+        bitShift = 0;
+        break;
+    case PortB:
+        bitShift = 4;
+        break;
+    case PortC:
+        bitShift = 8;
+        break;
+    case PortD:
+        bitShift = 12;
+        break;
+    }
+
+    switch (auxCommandSlot) {
+    case AuxCmd1:
+        dev->SetWireInValue(WireInAuxCmdBank1, bank << bitShift, 0x000f << bitShift);
+        break;
+    case AuxCmd2:
+        dev->SetWireInValue(WireInAuxCmdBank2, bank << bitShift, 0x000f << bitShift);
+        break;
+    case AuxCmd3:
+        dev->SetWireInValue(WireInAuxCmdBank3, bank << bitShift, 0x000f << bitShift);
+        break;
     }
     dev->UpdateWireIns();
 }
@@ -662,38 +617,34 @@ void Rhd2000EvalBoard::selectAuxCommandBank(BoardPort port, AuxCmdSlot auxComman
 // auxiliary command slot (AuxCmd1, AuxCmd2, or AuxCmd3).
 void Rhd2000EvalBoard::selectAuxCommandLength(AuxCmdSlot auxCommandSlot, int loopIndex, int endIndex)
 {
-    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3)
-    {
+    if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) {
         cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: auxCommandSlot out of range." << endl;
         return;
     }
 
-    if (loopIndex < 0 || loopIndex > 1023)
-    {
+    if (loopIndex < 0 || loopIndex > 1023) {
         cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: loopIndex out of range." << endl;
         return;
     }
 
-    if (endIndex < 0 || endIndex > 1023)
-    {
+    if (endIndex < 0 || endIndex > 1023) {
         cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: endIndex out of range." << endl;
         return;
     }
 
-    switch (auxCommandSlot)
-    {
-        case AuxCmd1:
-            dev->SetWireInValue(WireInAuxCmdLoop1, loopIndex);
-            dev->SetWireInValue(WireInAuxCmdLength1, endIndex);
-            break;
-        case AuxCmd2:
-            dev->SetWireInValue(WireInAuxCmdLoop2, loopIndex);
-            dev->SetWireInValue(WireInAuxCmdLength2, endIndex);
-            break;
-        case AuxCmd3:
-            dev->SetWireInValue(WireInAuxCmdLoop3, loopIndex);
-            dev->SetWireInValue(WireInAuxCmdLength3, endIndex);
-            break;
+    switch (auxCommandSlot) {
+    case AuxCmd1:
+        dev->SetWireInValue(WireInAuxCmdLoop1, loopIndex);
+        dev->SetWireInValue(WireInAuxCmdLength1, endIndex);
+        break;
+    case AuxCmd2:
+        dev->SetWireInValue(WireInAuxCmdLoop2, loopIndex);
+        dev->SetWireInValue(WireInAuxCmdLength2, endIndex);
+        break;
+    case AuxCmd3:
+        dev->SetWireInValue(WireInAuxCmdLoop3, loopIndex);
+        dev->SetWireInValue(WireInAuxCmdLength3, endIndex);
+        break;
     }
     dev->UpdateWireIns();
 }
@@ -712,12 +663,9 @@ void Rhd2000EvalBoard::resetBoard()
 // maxTimeStep is reached (if continuousMode == false).
 void Rhd2000EvalBoard::setContinuousRunMode(bool continuousMode)
 {
-    if (continuousMode)
-    {
+    if (continuousMode) {
         dev->SetWireInValue(WireInResetRun, 0x02, 0x02);
-    }
-    else
-    {
+    } else {
         dev->SetWireInValue(WireInResetRun, 0x00, 0x02);
     }
     dev->UpdateWireIns();
@@ -750,12 +698,9 @@ bool Rhd2000EvalBoard::isRunning() const
     dev->UpdateWireOuts();
     value = dev->GetWireOutValue(WireOutSpiRunning);
 
-    if ((value & 0x01) == 0)
-    {
+    if ((value & 0x01) == 0) {
         return false;
-    }
-    else
-    {
+    } else {
         return true;
     }
 }
@@ -784,26 +729,32 @@ void Rhd2000EvalBoard::setCableDelay(BoardPort port, int delay)
 {
     int bitShift;
 
-    if (delay < 0 || delay > 15)
-    {
-        cerr << "Error in Rhd2000EvalBoard::setCableDelay: delay out of range." << endl;
-        return;
-    }
-
-    switch (port)
-    {
-        case PortA:
-            bitShift = 0;
-            break;
-        case PortB:
-            bitShift = 4;
-            break;
-        case PortC:
-            bitShift = 8;
-            break;
-        case PortD:
-            bitShift = 12;
-            break;
+    if (delay < 0 || delay > 15) {
+        cerr << "Warning in Rhd2000EvalBoard::setCableDelay: delay out of range: " << delay  << endl;
+    }
+
+    if (delay < 0) delay = 0;
+    if (delay > 15) delay = 15;
+
+    switch (port) {
+    case PortA:
+        bitShift = 0;
+        cableDelay[0] = delay;
+        break;
+    case PortB:
+        bitShift = 4;
+        cableDelay[1] = delay;
+        break;
+    case PortC:
+        bitShift = 8;
+        cableDelay[2] = delay;
+        break;
+    case PortD:
+        bitShift = 12;
+        cableDelay[3] = delay;
+        break;
+    default:
+        cerr << "Error in RHD2000EvalBoard::setCableDelay: unknown port." << endl;
     }
 
     dev->SetWireInValue(WireInMisoDelay, delay << bitShift, 0x000f << bitShift);
@@ -822,17 +773,15 @@ void Rhd2000EvalBoard::setCableLengthMeters(BoardPort port, double lengthInMeter
     const double xilinxLvdsOutputDelay = 1.9e-9;    // 1.9 ns Xilinx LVDS output pin delay
     const double xilinxLvdsInputDelay = 1.4e-9;     // 1.4 ns Xilinx LVDS input pin delay
     const double rhd2000Delay = 9.0e-9;             // 9.0 ns RHD2000 SCLK-to-MISO delay
-    const double misoSettleTime = 10.0e-9;          // 10.0 ns delay after MISO changes, before we sample it
+    const double misoSettleTime = 6.7e-9;           // 6.7 ns delay after MISO changes, before we sample it
 
     tStep = 1.0 / (2800.0 * getSampleRate());  // data clock that samples MISO has a rate 35 x 80 = 2800x higher than the sampling rate
-    cableVelocity = 0.67 * speedOfLight;  // propogation velocity on cable is rougly 2/3 the speed of light
+    // cableVelocity = 0.67 * speedOfLight;  // propogation velocity on cable: version 1.3 and earlier
+    cableVelocity = 0.555 * speedOfLight;  // propogation velocity on cable: version 1.4 improvement based on cable measurements
     distance = 2.0 * lengthInMeters;      // round trip distance data must travel on cable
-    timeDelay = distance / cableVelocity + xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay + misoSettleTime;
-
-    delay = (int) ceil(timeDelay / tStep);
+    timeDelay = (distance / cableVelocity) + xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay + misoSettleTime;
 
-    // cout << "Total delay = " << (1e9 * timeDelay) << " ns" << endl;
-    // cout << "setCableLength: setting delay to " << delay << endl;
+    delay = (int) floor(((timeDelay / tStep) + 1.0) + 0.5);
 
     if (delay < 1) delay = 1;   // delay of zero is too short (due to I/O delays), even for zero-length cables
 
@@ -854,11 +803,14 @@ double Rhd2000EvalBoard::estimateCableLengthMeters(int delay) const
     const double xilinxLvdsOutputDelay = 1.9e-9;    // 1.9 ns Xilinx LVDS output pin delay
     const double xilinxLvdsInputDelay = 1.4e-9;     // 1.4 ns Xilinx LVDS input pin delay
     const double rhd2000Delay = 9.0e-9;             // 9.0 ns RHD2000 SCLK-to-MISO delay
+    const double misoSettleTime = 6.7e-9;           // 6.7 ns delay after MISO changes, before we sample it
 
     tStep = 1.0 / (2800.0 * getSampleRate());  // data clock that samples MISO has a rate 35 x 80 = 2800x higher than the sampling rate
-    cableVelocity = 0.67 * speedOfLight;  // propogation velocity on cable is rougly 2/3 the speed of light
+    // cableVelocity = 0.67 * speedOfLight;  // propogation velocity on cable: version 1.3 and earlier
+    cableVelocity = 0.555 * speedOfLight;  // propogation velocity on cable: version 1.4 improvement based on cable measurements
 
-    distance = cableVelocity * (delay * tStep - (xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay));
+    // distance = cableVelocity * (delay * tStep - (xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay));  // version 1.3 and earlier
+    distance = cableVelocity * ((((double) delay) - 1.0) * tStep - (xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay + misoSettleTime));  // version 1.4 improvement
     if (distance < 0.0) distance = 0.0;
 
     return (distance / 2.0);
@@ -884,83 +836,67 @@ void Rhd2000EvalBoard::setDataSource(int stream, BoardDataSource dataSource)
     int bitShift;
     OkEndPoint endPoint;
 
-    if (stream < 0 || stream > 7)
-    {
+    if (stream < 0 || stream > 7) {
         cerr << "Error in Rhd2000EvalBoard::setDataSource: stream out of range." << endl;
         return;
     }
 
-    switch (stream)
-    {
-        case 0:
-            endPoint = WireInDataStreamSel1234;
-            bitShift = 0;
-            break;
-        case 1:
-            endPoint = WireInDataStreamSel1234;
-            bitShift = 4;
-            break;
-        case 2:
-            endPoint = WireInDataStreamSel1234;
-            bitShift = 8;
-            break;
-        case 3:
-            endPoint = WireInDataStreamSel1234;
-            bitShift = 12;
-            break;
-        case 4:
-            endPoint = WireInDataStreamSel5678;
-            bitShift = 0;
-            break;
-        case 5:
-            endPoint = WireInDataStreamSel5678;
-            bitShift = 4;
-            break;
-        case 6:
-            endPoint = WireInDataStreamSel5678;
-            bitShift = 8;
-            break;
-        case 7:
-            endPoint = WireInDataStreamSel5678;
-            bitShift = 12;
-            break;
+    switch (stream) {
+    case 0:
+        endPoint = WireInDataStreamSel1234;
+        bitShift = 0;
+        break;
+    case 1:
+        endPoint = WireInDataStreamSel1234;
+        bitShift = 4;
+        break;
+    case 2:
+        endPoint = WireInDataStreamSel1234;
+        bitShift = 8;
+        break;
+    case 3:
+        endPoint = WireInDataStreamSel1234;
+        bitShift = 12;
+        break;
+    case 4:
+        endPoint = WireInDataStreamSel5678;
+        bitShift = 0;
+        break;
+    case 5:
+        endPoint = WireInDataStreamSel5678;
+        bitShift = 4;
+        break;
+    case 6:
+        endPoint = WireInDataStreamSel5678;
+        bitShift = 8;
+        break;
+    case 7:
+        endPoint = WireInDataStreamSel5678;
+        bitShift = 12;
+        break;
     }
 
     dev->SetWireInValue(endPoint, dataSource << bitShift, 0x000f << bitShift);
     dev->UpdateWireIns();
 }
 
-bool Rhd2000EvalBoard::isStreamEnabled(int streamIndex)
-{
-  if (streamIndex < 0 || streamIndex > (MAX_NUM_DATA_STREAMS - 1))
-    return false;
-
-  return dataStreamEnabled[streamIndex];
-}
-
 // Enable or disable one of the eight available USB data streams (0-7).
 void Rhd2000EvalBoard::enableDataStream(int stream, bool enabled)
 {
-    if (stream < 0 || stream > (MAX_NUM_DATA_STREAMS - 1))
-    {
+    if (stream < 0 || stream > (MAX_NUM_DATA_STREAMS - 1)) {
         cerr << "Error in Rhd2000EvalBoard::setDataSource: stream out of range." << endl;
         return;
     }
 
-    if (enabled)
-    {
-        if (dataStreamEnabled[stream] == 0)
-        {
+    if (enabled) {
+        if (dataStreamEnabled[stream] == 0) {
             dev->SetWireInValue(WireInDataStreamEn, 0x0001 << stream, 0x0001 << stream);
             dev->UpdateWireIns();
             dataStreamEnabled[stream] = 1;
             ++numDataStreams;
         }
-    }
-    else
-    {
-        if (dataStreamEnabled[stream] == 1)
-        {
+    } else {
+        if (dataStreamEnabled[stream] == 1) {
             dev->SetWireInValue(WireInDataStreamEn, 0x0000 << stream, 0x0001 << stream);
             dev->UpdateWireIns();
             dataStreamEnabled[stream] = 0;
@@ -988,8 +924,7 @@ void Rhd2000EvalBoard::setTtlOut(int ttlOutArray[])
     int i, ttlOut;
 
     ttlOut = 0;
-    for (i = 0; i < 16; ++i)
-    {
+    for (i = 0; i < 16; ++i) {
         if (ttlOutArray[i] > 0)
             ttlOut += 1 << i;
     }
@@ -1005,31 +940,22 @@ void Rhd2000EvalBoard::getTtlIn(int ttlInArray[])
     dev->UpdateWireOuts();
     ttlIn = dev->GetWireOutValue(WireOutTtlIn);
 
-    for (i = 0; i < 16; ++i)
-    {
+    for (i = 0; i < 16; ++i) {
         ttlInArray[i] = 0;
         if ((ttlIn & (1 << i)) > 0)
             ttlInArray[i] = 1;
     }
 }
 
-void Rhd2000EvalBoard::setDacManual(DacManual dac, int value)
+// Set manual value for DACs.
+void Rhd2000EvalBoard::setDacManual(int value)
 {
-    if (value < 0 || value > 65535)
-    {
+    if (value < 0 || value > 65535) {
         cerr << "Error in Rhd2000EvalBoard::setDacManual: value out of range." << endl;
         return;
     }
 
-    switch (dac)
-    {
-        case DacManual1:
-            dev->SetWireInValue(WireInDacManual1, value);
-            break;
-        case DacManual2:
-            dev->SetWireInValue(WireInDacManual2, value);
-            break;
-    }
+    dev->SetWireInValue(WireInDacManual, value);
     dev->UpdateWireIns();
 }
 
@@ -1039,8 +965,7 @@ void Rhd2000EvalBoard::setLedDisplay(int ledArray[])
     int i, ledOut;
 
     ledOut = 0;
-    for (i = 0; i < 8; ++i)
-    {
+    for (i = 0; i < 8; ++i) {
         if (ledArray[i] > 0)
             ledOut += 1 << i;
     }
@@ -1051,38 +976,36 @@ void Rhd2000EvalBoard::setLedDisplay(int ledArray[])
 // Enable or disable AD5662 DAC channel (0-7)
 void Rhd2000EvalBoard::enableDac(int dacChannel, bool enabled)
 {
-    if (dacChannel < 0 || dacChannel > 7)
-    {
+    if (dacChannel < 0 || dacChannel > 7) {
         cerr << "Error in Rhd2000EvalBoard::enableDac: dacChannel out of range." << endl;
         return;
     }
 
-    switch (dacChannel)
-    {
-        case 0:
-            dev->SetWireInValue(WireInDacSource1, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 1:
-            dev->SetWireInValue(WireInDacSource2, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 2:
-            dev->SetWireInValue(WireInDacSource3, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 3:
-            dev->SetWireInValue(WireInDacSource4, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 4:
-            dev->SetWireInValue(WireInDacSource5, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 5:
-            dev->SetWireInValue(WireInDacSource6, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 6:
-            dev->SetWireInValue(WireInDacSource7, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
-        case 7:
-            dev->SetWireInValue(WireInDacSource8, (enabled ? 0x0200 : 0x0000), 0x0200);
-            break;
+    switch (dacChannel) {
+    case 0:
+        dev->SetWireInValue(WireInDacSource1, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 1:
+        dev->SetWireInValue(WireInDacSource2, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 2:
+        dev->SetWireInValue(WireInDacSource3, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 3:
+        dev->SetWireInValue(WireInDacSource4, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 4:
+        dev->SetWireInValue(WireInDacSource5, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 5:
+        dev->SetWireInValue(WireInDacSource6, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 6:
+        dev->SetWireInValue(WireInDacSource7, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
+    case 7:
+        dev->SetWireInValue(WireInDacSource8, (enabled ? 0x0200 : 0x0000), 0x0200);
+        break;
     }
     dev->UpdateWireIns();
 }
@@ -1090,8 +1013,7 @@ void Rhd2000EvalBoard::enableDac(int dacChannel, bool enabled)
 // Set the gain level of all eight DAC channels to 2^gain (gain = 0-7).
 void Rhd2000EvalBoard::setDacGain(int gain)
 {
-    if (gain < 0 || gain > 7)
-    {
+    if (gain < 0 || gain > 7) {
         cerr << "Error in Rhd2000EvalBoard::setDacGain: gain out of range." << endl;
         return;
     }
@@ -1104,8 +1026,7 @@ void Rhd2000EvalBoard::setDacGain(int gain)
 // +16*noiseSuppress and -16*noiseSuppress LSBs.  (noiseSuppress = 0-127).
 void Rhd2000EvalBoard::setAudioNoiseSuppress(int noiseSuppress)
 {
-    if (noiseSuppress < 0 || noiseSuppress > 127)
-    {
+    if (noiseSuppress < 0 || noiseSuppress > 127) {
         cerr << "Error in Rhd2000EvalBoard::setAudioNoiseSuppress: noiseSuppress out of range." << endl;
         return;
     }
@@ -1114,160 +1035,169 @@ void Rhd2000EvalBoard::setAudioNoiseSuppress(int noiseSuppress)
     dev->UpdateWireIns();
 }
 
-// Assign a particular data stream (0-7) to a DAC channel (0-7).
+// Assign a particular data stream (0-7) to a DAC channel (0-7).  Setting stream
+// to 8 selects DacManual1 value; setting stream to 9 selects DacManual2 value.
 void Rhd2000EvalBoard::selectDacDataStream(int dacChannel, int stream)
 {
-    if (dacChannel < 0 || dacChannel > 7)
-    {
+    if (dacChannel < 0 || dacChannel > 7) {
         cerr << "Error in Rhd2000EvalBoard::selectDacDataStream: dacChannel out of range." << endl;
         return;
     }
 
-    if (stream < 0 || stream > 9)
-    {
+    if (stream < 0 || stream > 9) {
         cerr << "Error in Rhd2000EvalBoard::selectDacDataStream: stream out of range." << endl;
         return;
     }
-	dacStreamAssignment[dacChannel] = stream;
-    switch (dacChannel)
-    {
-        case 0:
-            dev->SetWireInValue(WireInDacSource1, stream << 5, 0x01e0);
-            break;
-        case 1:
-            dev->SetWireInValue(WireInDacSource2, stream << 5, 0x01e0);
-            break;
-        case 2:
-            dev->SetWireInValue(WireInDacSource3, stream << 5, 0x01e0);
-            break;
-        case 3:
-            dev->SetWireInValue(WireInDacSource4, stream << 5, 0x01e0);
-            break;
-        case 4:
-            dev->SetWireInValue(WireInDacSource5, stream << 5, 0x01e0);
-            break;
-        case 5:
-            dev->SetWireInValue(WireInDacSource6, stream << 5, 0x01e0);
-            break;
-        case 6:
-            dev->SetWireInValue(WireInDacSource7, stream << 5, 0x01e0);
-            break;
-        case 7:
-            dev->SetWireInValue(WireInDacSource8, stream << 5, 0x01e0);
-            break;
+
+    switch (dacChannel) {
+    case 0:
+        dev->SetWireInValue(WireInDacSource1, stream << 5, 0x01e0);
+        break;
+    case 1:
+        dev->SetWireInValue(WireInDacSource2, stream << 5, 0x01e0);
+        break;
+    case 2:
+        dev->SetWireInValue(WireInDacSource3, stream << 5, 0x01e0);
+        break;
+    case 3:
+        dev->SetWireInValue(WireInDacSource4, stream << 5, 0x01e0);
+        break;
+    case 4:
+        dev->SetWireInValue(WireInDacSource5, stream << 5, 0x01e0);
+        break;
+    case 5:
+        dev->SetWireInValue(WireInDacSource6, stream << 5, 0x01e0);
+        break;
+    case 6:
+        dev->SetWireInValue(WireInDacSource7, stream << 5, 0x01e0);
+        break;
+    case 7:
+        dev->SetWireInValue(WireInDacSource8, stream << 5, 0x01e0);
+        break;
     }
     dev->UpdateWireIns();
 }
 
-void Rhd2000EvalBoard::setFastSettleByTTL(bool state)
-
+// Assign a particular amplifier channel (0-31) to a DAC channel (0-7).
+void Rhd2000EvalBoard::selectDacDataChannel(int dacChannel, int dataChannel)
 {
-    dev->SetWireInValue(WireInResetRun, (state ? 0x10 : 0x00), 0x10);
-    dev->UpdateWireIns();
-}
+    if (dacChannel < 0 || dacChannel > 7) {
+        cerr << "Error in Rhd2000EvalBoard::selectDacDataChannel: dacChannel out of range." << endl;
+        return;
+    }
 
-void Rhd2000EvalBoard::setFastSettleByTTLchannel(int channel)
-{
-  if (channel < 0 || channel > 7)
-    {
-        cerr << "Error in Rhd2000EvalBoard::setFastSettleByTTLchannel: channel out of range." << endl;
+    if (dataChannel < 0 || dataChannel > 31) {
+        cerr << "Error in Rhd2000EvalBoard::selectDacDataChannel: dataChannel out of range." << endl;
         return;
     }
-// the WireInTTLSettleChannel is also used by DAC, so keep the values of 10 used bits
- // and shift the channel value 10 bits to the left
-    dev->SetWireInValue(WireInTTLSettleChannel, channel << 10, 0x3c00);
+
+    switch (dacChannel) {
+    case 0:
+        dev->SetWireInValue(WireInDacSource1, dataChannel << 0, 0x001f);
+        break;
+    case 1:
+        dev->SetWireInValue(WireInDacSource2, dataChannel << 0, 0x001f);
+        break;
+    case 2:
+        dev->SetWireInValue(WireInDacSource3, dataChannel << 0, 0x001f);
+        break;
+    case 3:
+        dev->SetWireInValue(WireInDacSource4, dataChannel << 0, 0x001f);
+        break;
+    case 4:
+        dev->SetWireInValue(WireInDacSource5, dataChannel << 0, 0x001f);
+        break;
+    case 5:
+        dev->SetWireInValue(WireInDacSource6, dataChannel << 0, 0x001f);
+        break;
+    case 6:
+        dev->SetWireInValue(WireInDacSource7, dataChannel << 0, 0x001f);
+        break;
+    case 7:
+        dev->SetWireInValue(WireInDacSource8, dataChannel << 0, 0x001f);
+        break;
+    }
     dev->UpdateWireIns();
 }
 
-
-
 // Enable external triggering of amplifier hardware 'fast settle' function (blanking).
-// If external triggering is enabled, this fast settling of amplifiers on all connected
+// If external triggering is enabled, the fast settling of amplifiers on all connected
 // chips will be controlled in real time via one of the 16 TTL inputs.
 void Rhd2000EvalBoard::enableExternalFastSettle(bool enable)
 {
-    fast_settle_enabled = enable;
     dev->SetWireInValue(WireInMultiUse, enable ? 1 : 0);
     dev->UpdateWireIns();
     dev->ActivateTriggerIn(TrigInExtFastSettle, 0);
 }
 
-bool Rhd2000EvalBoard::getExternalFastSettle()
-{
-    return fast_settle_enabled;
-}
 // Select which of the TTL inputs 0-15 is used to perform a hardware 'fast settle' (blanking)
-// of the amplifiers if external triggering of fast settling
-// is enabled.
+// of the amplifiers if external triggering of fast settling is enabled.
 void Rhd2000EvalBoard::setExternalFastSettleChannel(int channel)
 {
     if (channel < 0 || channel > 15) {
         cerr << "Error in Rhd2000EvalBoard::setExternalFastSettleChannel: channel out of range." << endl;
         return;
     }
+
     dev->SetWireInValue(WireInMultiUse, channel);
     dev->UpdateWireIns();
     dev->ActivateTriggerIn(TrigInExtFastSettle, 1);
 }
 
-int Rhd2000EvalBoard::gecDacDataChannel(int dacChannel)
+// Enable external control of RHD2000 auxiliary digital output pin (auxout).
+// If external control is enabled, the digital output of all chips connected to a
+// selected SPI port will be controlled in real time via one of the 16 TTL inputs.
+void Rhd2000EvalBoard::enableExternalDigOut(BoardPort port, bool enable)
 {
-    if (dacChannel < 0 || dacChannel > 7)
-        return -1;
-    return dacChannelAssignment[dacChannel];
-}
+    dev->SetWireInValue(WireInMultiUse, enable ? 1 : 0);
+    dev->UpdateWireIns();
 
-void Rhd2000EvalBoard::updateDacAssignment(int dacChannel, int stream, int channel)
-{
-	dacStreamAssignment[dacChannel] = stream;
-    dacChannelAssignment[dacChannel] = channel;
-	//selectDacDataStream
+    switch (port) {
+    case PortA:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 0);
+        break;
+    case PortB:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 1);
+        break;
+    case PortC:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 2);
+        break;
+    case PortD:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 3);
+        break;
+    default:
+        cerr << "Error in Rhd2000EvalBoard::enableExternalDigOut: port out of range." << endl;
+    }
 }
 
-// Assign a particular amplifier channel (0-31) to a DAC channel (0-7).
-void Rhd2000EvalBoard::selectDacDataChannel(int dacChannel, int dataChannel)
+// Select which of the TTL inputs 0-15 is used to control the auxiliary digital output
+// pin of the chips connected to a particular SPI port, if external control of auxout is enabled.
+void Rhd2000EvalBoard::setExternalDigOutChannel(BoardPort port, int channel)
 {
-    if (dacChannel < 0 || dacChannel > 7)
-    {
-        cerr << "Error in Rhd2000EvalBoard::selectDacDataChannel: dacChannel out of range." << endl;
+    if (channel < 0 || channel > 15) {
+        cerr << "Error in Rhd2000EvalBoard::setExternalDigOutChannel: channel out of range." << endl;
         return;
     }
 
-    if (dataChannel < 0 || dataChannel > 31)
-    {
-        cerr << "Error in Rhd2000EvalBoard::selectDacDataChannel: dataChannel out of range." << endl;
-        return;
-    }
-    dacChannelAssignment[dacChannel] = dataChannel;
+    dev->SetWireInValue(WireInMultiUse, channel);
+    dev->UpdateWireIns();
 
-    switch (dacChannel)
-    {
-        case 0:
-            dev->SetWireInValue(WireInDacSource1, dataChannel << 0, 0x001f);
-            break;
-        case 1:
-            dev->SetWireInValue(WireInDacSource2, dataChannel << 0, 0x001f);
-            break;
-        case 2:
-            dev->SetWireInValue(WireInDacSource3, dataChannel << 0, 0x001f);
-            break;
-        case 3:
-            dev->SetWireInValue(WireInDacSource4, dataChannel << 0, 0x001f);
-            break;
-        case 4:
-            dev->SetWireInValue(WireInDacSource5, dataChannel << 0, 0x001f);
-            break;
-        case 5:
-            dev->SetWireInValue(WireInDacSource6, dataChannel << 0, 0x001f);
-            break;
-        case 6:
-            dev->SetWireInValue(WireInDacSource7, dataChannel << 0, 0x001f);
-            break;
-        case 7:
-            dev->SetWireInValue(WireInDacSource8, dataChannel << 0, 0x001f);
-            break;
+    switch (port) {
+    case PortA:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 4);
+        break;
+    case PortB:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 5);
+        break;
+    case PortC:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 6);
+        break;
+    case PortD:
+        dev->ActivateTriggerIn(TrigInExtDigOut, 7);
+        break;
+    default:
+        cerr << "Error in Rhd2000EvalBoard::setExternalDigOutChannel: port out of range." << endl;
     }
-    dev->UpdateWireIns();
 }
 
 // Enable optional FPGA-implemented digital high-pass filters associated with DAC outputs
@@ -1316,28 +1246,7 @@ void Rhd2000EvalBoard::setDacHighpassFilter(double cutoff)
 // in the range of 0 to 65535, where the 'zero' level is 32768.
 // If trigPolarity is true, voltages equaling or rising above the threshold produce a high TTL output.
 // If trigPolarity is false, voltages equaling or falling below the threshold produce a high TTL output.
-//
-// To convert threshold in voltage to this range, use the following:
-//     int threshLevel = ((double) threshold / 0.195) + 32768;
-//    evalBoard->setDacThreshold(0, threshLevel, threshold >= 0);
-
-void Rhd2000EvalBoard::setDacThresholdVoltage(int dacChannel, float voltage_threshold)
-{
-     int threshLevel = (voltage_threshold / 0.195) + 32768;
-    setDacThreshold(dacChannel, abs(threshLevel), voltage_threshold >= 0);
-
-}
-
-void Rhd2000EvalBoard::getDacInformation(int *ch, float *th)
-{
-    for (int k=0;k<8;k++)
-    {
-        ch[k] = dacChannelAssignment[k];
-        th[k] = dacChannelThreshold[k];
-    }
-}
-
-void Rhd2000EvalBoard::setDacThreshold(int dacChannel, int threshold, bool trigPolarityPositive)
+void Rhd2000EvalBoard::setDacThreshold(int dacChannel, int threshold, bool trigPolarity)
 {
     if (dacChannel < 0 || dacChannel > 7) {
         cerr << "Error in Rhd2000EvalBoard::setDacThreshold: dacChannel out of range." << endl;
@@ -1348,7 +1257,6 @@ void Rhd2000EvalBoard::setDacThreshold(int dacChannel, int threshold, bool trigP
         cerr << "Error in Rhd2000EvalBoard::setDacThreshold: threshold out of range." << endl;
         return;
     }
-    dacChannelThreshold[dacChannel] = trigPolarityPositive? -(float)(threshold-32768)*0.195 : (float)(threshold-32768)*0.195;
 
     // Set threshold level.
     dev->SetWireInValue(WireInMultiUse, threshold);
@@ -1356,7 +1264,7 @@ void Rhd2000EvalBoard::setDacThreshold(int dacChannel, int threshold, bool trigP
     dev->ActivateTriggerIn(TrigInDacThresh, dacChannel);
 
     // Set threshold polarity.
-    dev->SetWireInValue(WireInMultiUse, (trigPolarityPositive ? 1 : 0));
+    dev->SetWireInValue(WireInMultiUse, (trigPolarity ? 1 : 0));
     dev->UpdateWireIns();
     dev->ActivateTriggerIn(TrigInDacThresh, dacChannel + 8);
 }
@@ -1402,28 +1310,25 @@ bool Rhd2000EvalBoard::isDataClockLocked() const
 // data acquisition has been stopped.)
 void Rhd2000EvalBoard::flush()
 {
-    while (numWordsInFifo() >= USB_BUFFER_SIZE / 2)
-    {
+    while (numWordsInFifo() >= USB_BUFFER_SIZE / 2) {
         dev->ReadFromPipeOut(PipeOutData, USB_BUFFER_SIZE, usbBuffer);
     }
-    while (numWordsInFifo() > 0)
-    {
+    while (numWordsInFifo() > 0) {
         dev->ReadFromPipeOut(PipeOutData, 2 * numWordsInFifo(), usbBuffer);
     }
 }
 
 // Read data block from the USB interface, if one is available.  Returns true if data block
 // was available.
-bool Rhd2000EvalBoard::readDataBlock(Rhd2000DataBlock* dataBlock)
+bool Rhd2000EvalBoard::readDataBlock(Rhd2000DataBlock *dataBlock)
 {
     unsigned int numBytesToRead;
 
     numBytesToRead = 2 * dataBlock->calculateDataBlockSizeInWords(numDataStreams);
 
-    if (numBytesToRead > USB_BUFFER_SIZE)
-    {
+    if (numBytesToRead > USB_BUFFER_SIZE) {
         cerr << "Error in Rhd2000EvalBoard::readDataBlock: USB buffer size exceeded.  " <<
-             "Increase value of USB_BUFFER_SIZE." << endl;
+                "Increase value of USB_BUFFER_SIZE." << endl;
         return false;
     }
 
@@ -1440,7 +1345,7 @@ bool Rhd2000EvalBoard::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &da
 {
     unsigned int numWordsToRead, numBytesToRead;
     int i;
-    Rhd2000DataBlock* dataBlock;
+    Rhd2000DataBlock *dataBlock;
 
     numWordsToRead = numBlocks * dataBlock->calculateDataBlockSizeInWords(numDataStreams);
 
@@ -1449,22 +1354,18 @@ bool Rhd2000EvalBoard::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &da
 
     numBytesToRead = 2 * numWordsToRead;
 
-    if (numBytesToRead > USB_BUFFER_SIZE)
-    {
+    if (numBytesToRead > USB_BUFFER_SIZE) {
         cerr << "Error in Rhd2000EvalBoard::readDataBlocks: USB buffer size exceeded.  " <<
-             "Increase value of USB_BUFFER_SIZE." << endl;
+                "Increase value of USB_BUFFER_SIZE." << endl;
         return false;
     }
 
     dev->ReadFromPipeOut(PipeOutData, numBytesToRead, usbBuffer);
 
     dataBlock = new Rhd2000DataBlock(numDataStreams);
-    for (i = 0; i < numBlocks; ++i)
-    {
-        // dataBlock = new Rhd2000DataBlock(numDataStreams);
+    for (i = 0; i < numBlocks; ++i) {
         dataBlock->fillFromUsbBuffer(usbBuffer, i, numDataStreams);
         dataQueue.push(*dataBlock);
-        // delete dataBlock;
     }
     delete dataBlock;
 
@@ -1473,12 +1374,11 @@ bool Rhd2000EvalBoard::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &da
 
 // Writes the contents of a data block queue (dataQueue) to a binary output stream (saveOut).
 // Returns the number of data blocks written.
-int Rhd2000EvalBoard::queueToFile(queue<Rhd2000DataBlock> &dataQueue, ofstream& saveOut)
+int Rhd2000EvalBoard::queueToFile(queue<Rhd2000DataBlock> &dataQueue, ofstream &saveOut)
 {
     int count = 0;
 
-    while (!dataQueue.empty())
-    {
+    while (!dataQueue.empty()) {
         dataQueue.front().write(saveOut, getNumEnabledDataStreams());
         dataQueue.pop();
         ++count;
@@ -1490,69 +1390,68 @@ int Rhd2000EvalBoard::queueToFile(queue<Rhd2000DataBlock> &dataQueue, ofstream&
 // Return name of Opal Kelly board based on model code.
 string Rhd2000EvalBoard::opalKellyModelName(int model) const
 {
-    switch (model)
-    {
-        case OK_PRODUCT_XEM3001V1:
-            return("XEM3001V1");
-        case OK_PRODUCT_XEM3001V2:
-            return("XEM3001V2");
-        case OK_PRODUCT_XEM3010:
-            return("XEM3010");
-        case OK_PRODUCT_XEM3005:
-            return("XEM3005");
-        case OK_PRODUCT_XEM3001CL:
-            return("XEM3001CL");
-        case OK_PRODUCT_XEM3020:
-            return("XEM3020");
-        case OK_PRODUCT_XEM3050:
-            return("XEM3050");
-        case OK_PRODUCT_XEM9002:
-            return("XEM9002");
-        case OK_PRODUCT_XEM3001RB:
-            return("XEM3001RB");
-        case OK_PRODUCT_XEM5010:
-            return("XEM5010");
-        case OK_PRODUCT_XEM6110LX45:
-            return("XEM6110LX45");
-        case OK_PRODUCT_XEM6001:
-            return("XEM6001");
-        case OK_PRODUCT_XEM6010LX45:
-            return("XEM6010LX45");
-        case OK_PRODUCT_XEM6010LX150:
-            return("XEM6010LX150");
-        case OK_PRODUCT_XEM6110LX150:
-            return("XEM6110LX150");
-        case OK_PRODUCT_XEM6006LX9:
-            return("XEM6006LX9");
-        case OK_PRODUCT_XEM6006LX16:
-            return("XEM6006LX16");
-        case OK_PRODUCT_XEM6006LX25:
-            return("XEM6006LX25");
-        case OK_PRODUCT_XEM5010LX110:
-            return("XEM5010LX110");
-        case OK_PRODUCT_ZEM4310:
-            return("ZEM4310");
-        case OK_PRODUCT_XEM6310LX45:
-            return("XEM6310LX45");
-        case OK_PRODUCT_XEM6310LX150:
-            return("XEM6310LX150");
-        case OK_PRODUCT_XEM6110V2LX45:
-            return("XEM6110V2LX45");
-        case OK_PRODUCT_XEM6110V2LX150:
-            return("XEM6110V2LX150");
-        case OK_PRODUCT_XEM6002LX9:
-            return("XEM6002LX9");
-        case OK_PRODUCT_XEM6310MTLX45:
-            return("XEM6310MTLX45");
-        case OK_PRODUCT_XEM6320LX130T:
-            return("XEM6320LX130T");
-        default:
-            return("UNKNOWN");
+    switch (model) {
+    case OK_PRODUCT_XEM3001V1:
+        return("XEM3001V1");
+    case OK_PRODUCT_XEM3001V2:
+        return("XEM3001V2");
+    case OK_PRODUCT_XEM3010:
+        return("XEM3010");
+    case OK_PRODUCT_XEM3005:
+        return("XEM3005");
+    case OK_PRODUCT_XEM3001CL:
+        return("XEM3001CL");
+    case OK_PRODUCT_XEM3020:
+        return("XEM3020");
+    case OK_PRODUCT_XEM3050:
+        return("XEM3050");
+    case OK_PRODUCT_XEM9002:
+        return("XEM9002");
+    case OK_PRODUCT_XEM3001RB:
+        return("XEM3001RB");
+    case OK_PRODUCT_XEM5010:
+        return("XEM5010");
+    case OK_PRODUCT_XEM6110LX45:
+        return("XEM6110LX45");
+    case OK_PRODUCT_XEM6001:
+        return("XEM6001");
+    case OK_PRODUCT_XEM6010LX45:
+        return("XEM6010LX45");
+    case OK_PRODUCT_XEM6010LX150:
+        return("XEM6010LX150");
+    case OK_PRODUCT_XEM6110LX150:
+        return("XEM6110LX150");
+    case OK_PRODUCT_XEM6006LX9:
+        return("XEM6006LX9");
+    case OK_PRODUCT_XEM6006LX16:
+        return("XEM6006LX16");
+    case OK_PRODUCT_XEM6006LX25:
+        return("XEM6006LX25");
+    case OK_PRODUCT_XEM5010LX110:
+        return("XEM5010LX110");
+    case OK_PRODUCT_ZEM4310:
+        return("ZEM4310");
+    case OK_PRODUCT_XEM6310LX45:
+        return("XEM6310LX45");
+    case OK_PRODUCT_XEM6310LX150:
+        return("XEM6310LX150");
+    case OK_PRODUCT_XEM6110V2LX45:
+        return("XEM6110V2LX45");
+    case OK_PRODUCT_XEM6110V2LX150:
+        return("XEM6110V2LX150");
+    case OK_PRODUCT_XEM6002LX9:
+        return("XEM6002LX9");
+    case OK_PRODUCT_XEM6310MTLX45:
+        return("XEM6310MTLX45");
+    case OK_PRODUCT_XEM6320LX130T:
+        return("XEM6320LX130T");
+    default:
+        return("UNKNOWN");
     }
 }
 
 // Return 4-bit "board mode" input.
-int Rhd2000EvalBoard::getBoardMode()
+int Rhd2000EvalBoard::getBoardMode() const
 {
     int mode;
 
@@ -1564,3 +1463,45 @@ int Rhd2000EvalBoard::getBoardMode()
     return mode;
 }
 
+// Return FPGA cable delay for selected SPI port.
+int Rhd2000EvalBoard::getCableDelay(BoardPort port) const
+{
+    switch (port) {
+    case PortA:
+        return cableDelay[0];
+    case PortB:
+        return cableDelay[1];
+    case PortC:
+        return cableDelay[2];
+    case PortD:
+        return cableDelay[3];
+    default:
+        cerr << "Error in RHD2000EvalBoard::getCableDelay: unknown port." << endl;
+        return -1;
+    }
+}
+
+// Return FPGA cable delays for all SPI ports.
+void Rhd2000EvalBoard::getCableDelay(vector<int> &delays) const
+{
+    if (delays.size() != 4) {
+        delays.resize(4);
+    }
+    for (int i = 0; i < 4; ++i) {
+        delays[i] = cableDelay[i];
+    }
+}
+
+// Uses the Opal Kelly library to reset the FPGA
+void Rhd2000EvalBoard::resetFpga() 
+{
+    dev->ResetFPGA();
+}
+
+bool Rhd2000EvalBoard::isStreamEnabled(int streamIndex)
+{
+  if (streamIndex < 0 || streamIndex > (MAX_NUM_DATA_STREAMS - 1))
+    return false;
+
+  return dataStreamEnabled[streamIndex];
+}
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.h b/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.h
index 3d670a18fbb935f0b736cafbc2b0769ef14ca8ab..a3238db0baf931549ddebd027ea044e3a270a456 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.h
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.h
@@ -3,9 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000EvalBoard Class Header File
-// Version 1.0 (14 January 2013)
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -38,14 +38,13 @@ class Rhd2000EvalBoard
 
 public:
     Rhd2000EvalBoard();
-    ~Rhd2000EvalBoard();
+	~Rhd2000EvalBoard();
 
-    int open(const char* libname);
+    int open(const char* libname); //patched to allow selecting path to dll
     bool uploadFpgaBitfile(string filename);
     void initialize();
 
-    enum AmplifierSampleRate
-    {
+    enum AmplifierSampleRate {
         SampleRate1000Hz,
         SampleRate1250Hz,
         SampleRate1500Hz,
@@ -69,15 +68,13 @@ public:
     double getSampleRate() const;
     AmplifierSampleRate getSampleRateEnum() const;
 
-    enum AuxCmdSlot
-    {
+    enum AuxCmdSlot {
         AuxCmd1,
         AuxCmd2,
         AuxCmd3
     };
 
-    enum BoardPort
-    {
+    enum BoardPort {
         PortA,
         PortB,
         PortC,
@@ -89,10 +86,6 @@ public:
     void selectAuxCommandBank(BoardPort port, AuxCmdSlot auxCommandSlot, int bank);
     void selectAuxCommandLength(AuxCmdSlot auxCommandSlot, int loopIndex, int endIndex);
 
-    void runImpedance();
-    bool getExternalFastSettle();
-
-
     void resetBoard();
     void setContinuousRunMode(bool continuousMode);
     void setMaxTimeStep(unsigned int maxTimeStep);
@@ -100,22 +93,16 @@ public:
     bool isRunning() const;
     unsigned int numWordsInFifo() const;
     static unsigned int fifoCapacityInWords();
-    void setDacThresholdVoltage(int dacChannel, float voltage_threshold);
-    void setDacThreshold(int dacChannel, int threshold, bool trigPolarity);
-    void enableDacHighpassFilter(bool enable);
-    void setDacHighpassFilter(double cutoff);
+
     void setCableDelay(BoardPort port, int delay);
     void setCableLengthMeters(BoardPort port, double lengthInMeters);
     void setCableLengthFeet(BoardPort port, double lengthInFeet);
     double estimateCableLengthMeters(int delay) const;
     double estimateCableLengthFeet(int delay) const;
-    void setTtlMode(int mode);
+
     void setDspSettle(bool enabled);
-    int getBoardMode();
-    void getDacInformation(int *ch, float *th);
 
-    enum BoardDataSource
-    {
+    enum BoardDataSource {
         PortA1 = 0,
         PortA2 = 1,
         PortB1 = 2,
@@ -136,20 +123,13 @@ public:
 
     void setDataSource(int stream, BoardDataSource dataSource);
     void enableDataStream(int stream, bool enabled);
-    bool isStreamEnabled(int streamIndex);
     int getNumEnabledDataStreams() const;
 
     void clearTtlOut();
     void setTtlOut(int ttlOutArray[]);
     void getTtlIn(int ttlInArray[]);
 
-    enum DacManual
-    {
-        DacManual1,
-        DacManual2
-    };
-
-    void setDacManual(DacManual dac, int value);
+    void setDacManual(int value);
 
     void setLedDisplay(int ledArray[]);
 
@@ -158,37 +138,39 @@ public:
     void setAudioNoiseSuppress(int noiseSuppress);
     void selectDacDataStream(int dacChannel, int stream);
     void selectDacDataChannel(int dacChannel, int dataChannel);
-
-    int gecDacDataChannel(int dacChannel);
-	void updateDacAssignment(int dacChannel, int stream, int channel);
     void enableExternalFastSettle(bool enable);
     void setExternalFastSettleChannel(int channel);
-    void setFastSettleByTTL(bool state);
-    void setFastSettleByTTLchannel(int channel);
+    void enableExternalDigOut(BoardPort port, bool enable);
+    void setExternalDigOutChannel(BoardPort port, int channel);
+    void enableDacHighpassFilter(bool enable);
+    void setDacHighpassFilter(double cutoff);
+    void setDacThreshold(int dacChannel, int threshold, bool trigPolarity);
+    void setTtlMode(int mode);
 
     void flush();
-    bool readDataBlock(Rhd2000DataBlock* dataBlock);
+    bool readDataBlock(Rhd2000DataBlock *dataBlock);
     bool readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue);
-    int queueToFile(queue<Rhd2000DataBlock> &dataQueue, std::ofstream& saveOut);
+    int queueToFile(queue<Rhd2000DataBlock> &dataQueue, std::ofstream &saveOut);
+    int getBoardMode() const;
+    int getCableDelay(BoardPort port) const;
+    void getCableDelay(vector<int> &delays) const;
 
-    void resetFpga();
+	//Additions by open-ephys
+	void resetFpga();
+	bool isStreamEnabled(int streamIndex);
 
 private:
-    okCFrontPanel* dev;
+    okCFrontPanel *dev;
     AmplifierSampleRate sampleRate;
     int numDataStreams; // total number of data streams currently enabled
     int dataStreamEnabled[MAX_NUM_DATA_STREAMS]; // 0 (disabled) or 1 (enabled)
-    int *dacChannelAssignment;
-	int *dacStreamAssignment;
-    float *dacChannelThreshold;
-    bool fast_settle_enabled;
+    vector<int> cableDelay;
 
     // Buffer for reading bytes from USB interface
     unsigned char usbBuffer[USB_BUFFER_SIZE];
 
     // Opal Kelly module USB interface endpoint addresses
-    enum OkEndPoint
-    {
+    enum OkEndPoint {
         WireInResetRun = 0x00,
         WireInMaxTimeStepLsb = 0x01,
         WireInMaxTimeStepMsb = 0x02,
@@ -219,18 +201,16 @@ private:
         WireInDacSource6 = 0x1b,
         WireInDacSource7 = 0x1c,
         WireInDacSource8 = 0x1d,
-        WireInDacManual1 = 0x1e,
-        WireInDacManual2 = 0x1f,
-        WireInMultiUse = 0x1f, 
+        WireInDacManual = 0x1e,
+        WireInMultiUse = 0x1f,
 
-        WireInTTLSettleChannel   = 0x16,
         TrigInDcmProg = 0x40,
         TrigInSpiStart = 0x41,
         TrigInRamWrite = 0x42,
         TrigInDacThresh = 0x43,
         TrigInDacHpf = 0x44,
         TrigInExtFastSettle = 0x45,
-
+        TrigInExtDigOut = 0x46,
 
         WireOutNumWordsLsb = 0x20,
         WireOutNumWordsMsb = 0x21,
@@ -249,6 +229,7 @@ private:
 
     bool isDcmProgDone() const;
     bool isDataClockLocked() const;
+
 };
 
 #endif // RHD2000EVALBOARD_H
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000registers.cpp b/Source/Processors/DataThreads/rhythm-api/rhd2000registers.cpp
index 3fe9e2aa6ad861140b86296c2ed4b5a3b139500d..e2857da04086d095adfe0537d2ca5e813eb74811 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000registers.cpp
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000registers.cpp
@@ -3,9 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000Registers Class
-// Version 1.0 (14 January 2013)
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -20,10 +20,9 @@
 
 #include <iostream>
 #include <iomanip>
-#include <math.h>
+#include <cmath>
 #include <vector>
 #include <queue>
-#include <cmath>
 
 #include "rhd2000registers.h"
 
@@ -38,41 +37,41 @@ using namespace std;
 // Constructor.  Set RHD2000 register variables to default values.
 Rhd2000Registers::Rhd2000Registers(double sampleRate)
 {
-    aPwr.resize(32);
+    aPwr.resize(64);
 
     defineSampleRate(sampleRate);
 
     // Set default values for all register settings
     adcReferenceBw = 3;         // ADC reference generator bandwidth (0 [highest BW] - 3 [lowest BW]);
-    // always set to 3
+                                // always set to 3
     setFastSettle(false);       // amplifier fast settle (off = normal operation)
     ampVrefEnable = 1;          // enable amplifier voltage references (0 = power down; 1 = enable);
-    // 1 = normal operation
+                                // 1 = normal operation
     adcComparatorBias = 3;      // ADC comparator preamp bias current (0 [lowest] - 3 [highest], only
-    // valid for comparator select = 2,3); always set to 3
+                                // valid for comparator select = 2,3); always set to 3
     adcComparatorSelect = 2;    // ADC comparator select; always set to 2
 
     vddSenseEnable = 1;         // supply voltage sensor enable (0 = disable; 1 = enable)
     // adcBufferBias = 32;      // ADC reference buffer bias current (0 [highest current] - 63 [lowest current]);
-    // This value should be set according to ADC sampling rate; set in setSampleRate()
+                                // This value should be set according to ADC sampling rate; set in setSampleRate()
 
     // muxBias = 40;            // ADC input MUX bias current (0 [highest current] - 63 [lowest current]);
-    // This value should be set according to ADC sampling rate; set in setSampleRate()
+                                // This value should be set according to ADC sampling rate; set in setSampleRate()
 
     // muxLoad = 0;             // MUX capacitance load at ADC input (0 [min CL] - 7 [max CL]); LSB = 3 pF
-    // Set in setSampleRate()
+                                // Set in setSampleRate()
 
     tempS1 = 0;                 // temperature sensor S1 (0-1); 0 = power saving mode when temperature sensor is
-    // not in use
+                                // not in use
     tempS2 = 0;                 // temperature sensor S2 (0-1); 0 = power saving mode when temperature sensor is
-    // not in use
+                                // not in use
     tempEn = 0;                 // temperature sensor enable (0 = disable; 1 = enable)
     setDigOutHiZ();             // auxiliary digital output state
 
     weakMiso = 1;               // weak MISO (0 = MISO line is HiZ when CS is inactive; 1 = MISO line is weakly
-    // driven when CS is inactive)
+                                // driven when CS is inactive)
     twosComp = 0;               // two's complement ADC results (0 = unsigned offset representation; 1 = signed
-    // representation)
+                                // representation)
     absMode = 0;                // absolute value mode (0 = normal output; 1 = output passed through abs(x) function)
     enableDsp(true);            // DSP offset removal enable/disable
     setDspCutoffFreq(1.0);      // DSP offset removal HPF cutoff freqeuncy
@@ -82,10 +81,10 @@ Rhd2000Registers::Rhd2000Registers(double sampleRate)
     setZcheckScale(ZcheckCs100fF);  // impedance testing scale factor (100 fF, 1.0 pF, or 10.0 pF)
     zcheckConnAll = 0;          // impedance testing connect all (0 = normal operation; 1 = connect all electrodes together)
     setZcheckPolarity(ZcheckPositiveInput); // impedance testing polarity select (RHD2216 only) (0 = test positive inputs;
-    // 1 = test negative inputs)
+                                // 1 = test negative inputs)
     enableZcheck(false);        // impedance testing enable/disable
 
-    setZcheckChannel(0);        // impedance testing amplifier select (0-63, but MSB is ignored, so 0-31 in practice)
+    setZcheckChannel(0);        // impedance testing amplifier select (0-63)
 
     offChipRH1 = 0;             // bandwidth resistor RH1 on/off chip (0 = on chip; 1 = off chip)
     offChipRH2 = 0;             // bandwidth resistor RH2 on/off chip (0 = on chip; 1 = off chip)
@@ -108,48 +107,31 @@ void Rhd2000Registers::defineSampleRate(double newSampleRate)
 
     muxLoad = 0;
 
-    if (sampleRate < 3334.0)
-    {
+    if (sampleRate < 3334.0) {
         muxBias = 40;
         adcBufferBias = 32;
-    }
-    else if (sampleRate < 4001.0)
-    {
+    } else if (sampleRate < 4001.0) {
         muxBias = 40;
         adcBufferBias = 16;
-    }
-    else if (sampleRate < 5001.0)
-    {
+    } else if (sampleRate < 5001.0) {
         muxBias = 40;
         adcBufferBias = 8;
-    }
-    else if (sampleRate < 6251.0)
-    {
+    } else if (sampleRate < 6251.0) {
         muxBias = 32;
         adcBufferBias = 8;
-    }
-    else if (sampleRate < 8001.0)
-    {
+    } else if (sampleRate < 8001.0) {
         muxBias = 26;
         adcBufferBias = 8;
-    }
-    else if (sampleRate < 10001.0)
-    {
+    } else if (sampleRate < 10001.0) {
         muxBias = 18;
         adcBufferBias = 4;
-    }
-    else if (sampleRate < 12501.0)
-    {
+    } else if (sampleRate < 12501.0) {
         muxBias = 16;
         adcBufferBias = 3;
-    }
-    else if (sampleRate < 15001.0)
-    {
+    } else if (sampleRate < 15001.0) {
         muxBias = 7;
         adcBufferBias = 3;
-    }
-    else
-    {
+    } else {
         muxBias = 4;
         adcBufferBias = 2;
     }
@@ -220,8 +202,7 @@ double Rhd2000Registers::setDspCutoffFreq(double newDspCutoffFreq)
     logNewDspCutoffFreq = log10(newDspCutoffFreq);
 
     // Generate table of all possible DSP cutoff frequencies
-    for (n = 1; n < 16; ++n)
-    {
+    for (n = 1; n < 16; ++n) {
         x = pow(2.0, (double) n);
         fCutoff[n] = sampleRate * log(x / (x - 1.0)) / (2*Pi);
         logFCutoff[n] = log10(fCutoff[n]);
@@ -229,21 +210,14 @@ double Rhd2000Registers::setDspCutoffFreq(double newDspCutoffFreq)
     }
 
     // Now find the closest value to the requested cutoff frequency (on a logarithmic scale)
-    if (newDspCutoffFreq > fCutoff[1])
-    {
+    if (newDspCutoffFreq > fCutoff[1]) {
         dspCutoffFreq = 1;
-    }
-    else if (newDspCutoffFreq < fCutoff[15])
-    {
+    } else if (newDspCutoffFreq < fCutoff[15]) {
         dspCutoffFreq = 15;
-    }
-    else
-    {
+    } else {
         minLogDiff = 10000000.0;
-        for (n = 1; n < 16; ++n)
-        {
-            if (abs(logNewDspCutoffFreq - logFCutoff[n]) < minLogDiff)
-            {
+        for (n = 1; n < 16; ++n) {
+            if (abs(logNewDspCutoffFreq - logFCutoff[n]) < minLogDiff) {
                 minLogDiff = abs(logNewDspCutoffFreq - logFCutoff[n]);
                 dspCutoffFreq = n;
             }
@@ -281,8 +255,7 @@ void Rhd2000Registers::setZcheckDacPower(bool enabled)
 // (ZcheckCs100fF, ZcheckCs1pF, or Zcheck10pF).
 void Rhd2000Registers::setZcheckScale(ZcheckCs scale)
 {
-    switch (scale)
-    {
+    switch (scale) {
         case ZcheckCs100fF:
             zcheckScale = 0x00;     // Cs = 0.1 pF
             break;
@@ -299,26 +272,22 @@ void Rhd2000Registers::setZcheckScale(ZcheckCs scale)
 // on the variable polarity (ZcheckPositiveInput or ZcheckNegativeInput)
 void Rhd2000Registers::setZcheckPolarity(ZcheckPolarity polarity)
 {
-    switch (polarity)
-    {
+    switch (polarity) {
         case ZcheckPositiveInput:
             zcheckSelPol = 0;
             break;
-        case ZcheckNegativeInput:
+    case ZcheckNegativeInput:
             zcheckSelPol = 1;
             break;
     }
 }
 
-// Select the amplifier channel (0-31) for impedance testing.
+// Select the amplifier channel (0-63) for impedance testing.
 int Rhd2000Registers::setZcheckChannel(int channel)
 {
-    if (channel < 0 || channel > 31)
-    {
+    if (channel < 0 || channel > 63) {
         return -1;
-    }
-    else
-    {
+    } else {
         zcheckSelect = channel;
         return zcheckSelect;
     }
@@ -327,8 +296,7 @@ int Rhd2000Registers::setZcheckChannel(int channel)
 // Power up or down selected amplifier on chip
 void Rhd2000Registers::setAmpPowered(int channel, bool powered)
 {
-    if (channel >= 0 && channel <= 31)
-    {
+    if (channel >= 0 && channel <= 63) {
         aPwr[channel] = (powered ? 1 : 0);
     }
 }
@@ -336,8 +304,7 @@ void Rhd2000Registers::setAmpPowered(int channel, bool powered)
 // Power up all amplifiers on chip
 void Rhd2000Registers::powerUpAllAmps()
 {
-    for (int channel = 0; channel < 32; ++channel)
-    {
+    for (int channel = 0; channel < 64; ++channel) {
         aPwr[channel] = 1;
     }
 }
@@ -345,8 +312,7 @@ void Rhd2000Registers::powerUpAllAmps()
 // Power down all amplifiers on chip
 void Rhd2000Registers::powerDownAllAmps()
 {
-    for (int channel = 0; channel < 32; ++channel)
-    {
+    for (int channel = 0; channel < 64; ++channel) {
         aPwr[channel] = 0;
     }
 }
@@ -358,72 +324,87 @@ int Rhd2000Registers::getRegisterValue(int reg) const
     int regout;
     const int zcheckDac = 128;  // midrange
 
-    switch (reg)
-    {
-        case 0:
-            regout = (adcReferenceBw << 6) + (ampFastSettle << 5) + (ampVrefEnable << 4) +
-                     (adcComparatorBias << 2) + adcComparatorSelect;
-            break;
-        case 1:
-            regout = (vddSenseEnable << 6) + adcBufferBias;
-            break;
-        case 2:
-            regout = muxBias;
-            break;
-        case 3:
-            regout = (muxLoad << 5) + (tempS2 << 4) + (tempS1 << 3) + (tempEn << 2) +
-                     (digOutHiZ << 1) + digOut;
-            break;
-        case 4:
-            regout = (weakMiso << 7) + (twosComp << 6) + (absMode << 5) + (dspEn << 4) +
-                     dspCutoffFreq;
-            break;
-        case 5:
-            regout = (zcheckDacPower << 6) + (zcheckLoad << 5) + (zcheckScale << 3) +
-                     (zcheckConnAll << 2) + (zcheckSelPol << 1) + zcheckEn;
-            break;
-        case 6:
-            regout = zcheckDac;
-            break;
-        case 7:
-            regout = zcheckSelect;
-            break;
-        case 8:
-            regout = (offChipRH1 << 7) + rH1Dac1;
-            break;
-        case 9:
-            regout = (adcAux1En << 7) + rH1Dac2;
-            break;
-        case 10:
-            regout = (offChipRH2 << 7) + rH2Dac1;
-            break;
-        case 11:
-            regout = (adcAux2En << 7) + rH2Dac2;
-            break;
-        case 12:
-            regout = (offChipRL << 7) + rLDac1;
-            break;
-        case 13:
-            regout = (adcAux3En << 7) + (rLDac3 << 6) + rLDac2;
-            break;
-        case 14:
-            regout = (aPwr[7] << 7) + (aPwr[6] << 6) + (aPwr[5] << 5) + (aPwr[4] << 4) +
-                     (aPwr[3] << 3) + (aPwr[2] << 2) + (aPwr[1] << 1) + aPwr[0];
-            break;
-        case 15:
-            regout = (aPwr[15] << 7) + (aPwr[14] << 6) + (aPwr[13] << 5) + (aPwr[12] << 4) +
-                     (aPwr[11] << 3) + (aPwr[10] << 2) + (aPwr[9] << 1) + aPwr[0];
-            break;
-        case 16:
-            regout = (aPwr[23] << 7) + (aPwr[22] << 6) + (aPwr[21] << 5) + (aPwr[20] << 4) +
-                     (aPwr[19] << 3) + (aPwr[18] << 2) + (aPwr[17] << 1) + aPwr[16];
-            break;
-        case 17:
-            regout = (aPwr[31] << 7) + (aPwr[30] << 6) + (aPwr[29] << 5) + (aPwr[28] << 4) +
-                     (aPwr[27] << 3) + (aPwr[26] << 2) + (aPwr[25] << 1) + aPwr[24];
-            break;
-        default:
-            regout = -1;
+    switch (reg) {
+    case 0:
+        regout = (adcReferenceBw << 6) + (ampFastSettle << 5) + (ampVrefEnable << 4) +
+                (adcComparatorBias << 2) + adcComparatorSelect;
+        break;
+    case 1:
+        regout = (vddSenseEnable << 6) + adcBufferBias;
+        break;
+    case 2:
+        regout = muxBias;
+        break;
+    case 3:
+        regout = (muxLoad << 5) + (tempS2 << 4) + (tempS1 << 3) + (tempEn << 2) +
+                (digOutHiZ << 1) + digOut;
+        break;
+    case 4:
+        regout = (weakMiso << 7) + (twosComp << 6) + (absMode << 5) + (dspEn << 4) +
+                dspCutoffFreq;
+        break;
+    case 5:
+        regout = (zcheckDacPower << 6) + (zcheckLoad << 5) + (zcheckScale << 3) +
+                (zcheckConnAll << 2) + (zcheckSelPol << 1) + zcheckEn;
+        break;
+    case 6:
+        regout = zcheckDac;
+        break;
+    case 7:
+        regout = zcheckSelect;
+        break;
+    case 8:
+        regout = (offChipRH1 << 7) + rH1Dac1;
+        break;
+    case 9:
+        regout = (adcAux1En << 7) + rH1Dac2;
+        break;
+    case 10:
+        regout = (offChipRH2 << 7) + rH2Dac1;
+        break;
+    case 11:
+        regout = (adcAux2En << 7) + rH2Dac2;
+        break;
+    case 12:
+        regout = (offChipRL << 7) + rLDac1;
+        break;
+    case 13:
+        regout = (adcAux3En << 7) + (rLDac3 << 6) + rLDac2;
+        break;
+    case 14:
+        regout = (aPwr[7] << 7) + (aPwr[6] << 6) + (aPwr[5] << 5) + (aPwr[4] << 4) +
+                (aPwr[3] << 3) + (aPwr[2] << 2) + (aPwr[1] << 1) + aPwr[0];
+        break;
+    case 15:
+        regout = (aPwr[15] << 7) + (aPwr[14] << 6) + (aPwr[13] << 5) + (aPwr[12] << 4) +
+                (aPwr[11] << 3) + (aPwr[10] << 2) + (aPwr[9] << 1) + aPwr[0];
+        break;
+    case 16:
+        regout = (aPwr[23] << 7) + (aPwr[22] << 6) + (aPwr[21] << 5) + (aPwr[20] << 4) +
+                (aPwr[19] << 3) + (aPwr[18] << 2) + (aPwr[17] << 1) + aPwr[16];
+        break;
+    case 17:
+        regout = (aPwr[31] << 7) + (aPwr[30] << 6) + (aPwr[29] << 5) + (aPwr[28] << 4) +
+                (aPwr[27] << 3) + (aPwr[26] << 2) + (aPwr[25] << 1) + aPwr[24];
+        break;
+    case 18:
+        regout = (aPwr[39] << 7) + (aPwr[38] << 6) + (aPwr[37] << 5) + (aPwr[36] << 4) +
+                (aPwr[35] << 3) + (aPwr[34] << 2) + (aPwr[33] << 1) + aPwr[32];
+        break;
+    case 19:
+        regout = (aPwr[47] << 7) + (aPwr[46] << 6) + (aPwr[45] << 5) + (aPwr[44] << 4) +
+                (aPwr[43] << 3) + (aPwr[42] << 2) + (aPwr[41] << 1) + aPwr[40];
+        break;
+    case 20:
+        regout = (aPwr[55] << 7) + (aPwr[54] << 6) + (aPwr[53] << 5) + (aPwr[52] << 4) +
+                (aPwr[51] << 3) + (aPwr[50] << 2) + (aPwr[49] << 1) + aPwr[48];
+        break;
+    case 21:
+        regout = (aPwr[63] << 7) + (aPwr[62] << 6) + (aPwr[61] << 5) + (aPwr[60] << 4) +
+                (aPwr[59] << 3) + (aPwr[58] << 2) + (aPwr[57] << 1) + aPwr[56];
+        break;
+    default:
+        regout = -1;
     }
     return regout;
 }
@@ -452,13 +433,10 @@ double Rhd2000Registers::rLFromLowerBandwidth(double lowerBandwidth) const
 {
     double log10f = log10(lowerBandwidth);
 
-    if (lowerBandwidth < 4.0)
-    {
+    if (lowerBandwidth < 4.0) {
         return 1.0061 * pow(10.0, (4.9391 - 1.2088 * log10f + 0.5698 * log10f * log10f +
                                    0.1442 * log10f * log10f * log10f));
-    }
-    else
-    {
+    } else {
         return 1.0061 * pow(10.0, (4.7351 - 0.5916 * log10f + 0.08482 * log10f * log10f));
     }
 }
@@ -496,19 +474,15 @@ double Rhd2000Registers::lowerBandwidthFromRL(double rL) const
     double a, b, c;
 
     // Quadratic fit below is invalid for values of RL less than 5.1 kOhm
-    if (rL < 5100.0)
-    {
+    if (rL < 5100.0) {
         rL = 5100.0;
     }
 
-    if (rL < 30000.0)
-    {
+    if (rL < 30000.0) {
         a = 0.08482;
         b = -0.5916;
         c = 4.7351 - log10(rL/1.0061);
-    }
-    else
-    {
+    } else {
         a = 0.3303;
         b = -1.2100;
         c = 4.9873 - log10(rL/1.0061);
@@ -539,8 +513,7 @@ double Rhd2000Registers::setUpperBandwidth(double upperBandwidth)
     int i;
 
     // Upper bandwidths higher than 30 kHz don't work well with the RHD2000 amplifiers
-    if (upperBandwidth > 30000.0)
-    {
+    if (upperBandwidth > 30000.0) {
         upperBandwidth = 30000.0;
     }
 
@@ -550,19 +523,15 @@ double Rhd2000Registers::setUpperBandwidth(double upperBandwidth)
     rH1Dac2 = 0;
     rH1Actual = RH1Base;
 
-    for (i = 0; i < RH1Dac2Steps; ++i)
-    {
-        if (rH1Actual < rH1Target - (RH1Dac2Unit - RH1Dac1Unit / 2))
-        {
+    for (i = 0; i < RH1Dac2Steps; ++i) {
+        if (rH1Actual < rH1Target - (RH1Dac2Unit - RH1Dac1Unit / 2)) {
             rH1Actual += RH1Dac2Unit;
             ++rH1Dac2;
         }
     }
 
-    for (i = 0; i < RH1Dac1Steps; ++i)
-    {
-        if (rH1Actual < rH1Target - (RH1Dac1Unit / 2))
-        {
+    for (i = 0; i < RH1Dac1Steps; ++i) {
+        if (rH1Actual < rH1Target - (RH1Dac1Unit / 2)) {
             rH1Actual += RH1Dac1Unit;
             ++rH1Dac1;
         }
@@ -574,19 +543,15 @@ double Rhd2000Registers::setUpperBandwidth(double upperBandwidth)
     rH2Dac2 = 0;
     rH2Actual = RH2Base;
 
-    for (i = 0; i < RH2Dac2Steps; ++i)
-    {
-        if (rH2Actual < rH2Target - (RH2Dac2Unit - RH2Dac1Unit / 2))
-        {
+    for (i = 0; i < RH2Dac2Steps; ++i) {
+        if (rH2Actual < rH2Target - (RH2Dac2Unit - RH2Dac1Unit / 2)) {
             rH2Actual += RH2Dac2Unit;
             ++rH2Dac2;
         }
     }
 
-    for (i = 0; i < RH2Dac1Steps; ++i)
-    {
-        if (rH2Actual < rH2Target - (RH2Dac1Unit / 2))
-        {
+    for (i = 0; i < RH2Dac1Steps; ++i) {
+        if (rH2Actual < rH2Target - (RH2Dac1Unit / 2)) {
             rH2Actual += RH2Dac1Unit;
             ++rH2Dac1;
         }
@@ -643,8 +608,7 @@ double Rhd2000Registers::setLowerBandwidth(double lowerBandwidth)
     int i;
 
     // Lower bandwidths higher than 1.5 kHz don't work well with the RHD2000 amplifiers
-    if (lowerBandwidth > 1500.0)
-    {
+    if (lowerBandwidth > 1500.0) {
         lowerBandwidth = 1500.0;
     }
 
@@ -655,25 +619,20 @@ double Rhd2000Registers::setLowerBandwidth(double lowerBandwidth)
     rLDac3 = 0;
     rLActual = RLBase;
 
-    if (lowerBandwidth < 0.15)
-    {
+    if (lowerBandwidth < 0.15) {
         rLActual += RLDac3Unit;
         ++rLDac3;
     }
 
-    for (i = 0; i < RLDac2Steps; ++i)
-    {
-        if (rLActual < rLTarget - (RLDac2Unit - RLDac1Unit / 2))
-        {
+    for (i = 0; i < RLDac2Steps; ++i) {
+        if (rLActual < rLTarget - (RLDac2Unit - RLDac1Unit / 2)) {
             rLActual += RLDac2Unit;
             ++rLDac2;
         }
     }
 
-    for (i = 0; i < RLDac1Steps; ++i)
-    {
-        if (rLActual < rLTarget - (RLDac1Unit / 2))
-        {
+    for (i = 0; i < RLDac1Steps; ++i) {
+        if (rLActual < rLTarget - (RLDac1Unit / 2)) {
             rLActual += RLDac1Unit;
             ++rLDac1;
         }
@@ -706,8 +665,7 @@ double Rhd2000Registers::setLowerBandwidth(double lowerBandwidth)
 // Return a 16-bit MOSI command (CALIBRATE or CLEAR)
 int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType)
 {
-    switch (commandType)
-    {
+    switch (commandType) {
         case Rhd2000CommandCalibrate:
             return 0x5500;   // 0101010100000000
             break;
@@ -715,8 +673,8 @@ int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType)
             return 0x6a00;   // 0110101000000000
             break;
         default:
-            cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                 "Only 'Calibrate' or 'Clear Calibration' commands take zero arguments." << endl;
+        cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
+                "Only 'Calibrate' or 'Clear Calibration' commands take zero arguments." << endl;
             return -1;
     }
 }
@@ -724,30 +682,27 @@ int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType)
 // Return a 16-bit MOSI command (CONVERT or READ)
 int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType, int arg1)
 {
-    switch (commandType)
-    {
+    switch (commandType) {
         case Rhd2000CommandConvert:
-            if (arg1 < 0 || arg1 > 63)
-            {
+            if (arg1 < 0 || arg1 > 63) {
                 cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                     "Channel number out of range." << endl;
+                        "Channel number out of range." << endl;
                 return -1;
             }
             return 0x0000 + (arg1 << 8);  // 00cccccc0000000h; if the command is 'Convert',
-            // arg1 is the channel number
+                                          // arg1 is the channel number
         case Rhd2000CommandRegRead:
-            if (arg1 < 0 || arg1 > 63)
-            {
+            if (arg1 < 0 || arg1 > 63) {
                 cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                     "Register address out of range." << endl;
+                        "Register address out of range." << endl;
                 return -1;
             }
             return 0xc000 + (arg1 << 8);  // 11rrrrrr00000000; if the command is 'Register Read',
-            // arg1 is the register address
+                                          // arg1 is the register address
             break;
         default:
             cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                 "Only 'Convert' and 'Register Read' commands take one argument." << endl;
+                    "Only 'Convert' and 'Register Read' commands take one argument." << endl;
             return -1;
     }
 }
@@ -755,35 +710,33 @@ int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType, int a
 // Return a 16-bit MOSI command (WRITE)
 int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType, int arg1, int arg2)
 {
-    switch (commandType)
-    {
+    switch (commandType) {
         case Rhd2000CommandRegWrite:
-            if (arg1 < 0 || arg1 > 63)
-            {
+            if (arg1 < 0 || arg1 > 63) {
                 cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                     "Register address out of range." << endl;
+                        "Register address out of range." << endl;
                 return -1;
             }
-            if (arg2 < 0 || arg2 > 255)
-            {
+            if (arg2 < 0 || arg2 > 255) {
                 cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                     "Register data out of range." << endl;
+                        "Register data out of range." << endl;
                 return -1;
             }
             return 0x8000 + (arg1 << 8) + arg2; // 10rrrrrrdddddddd; if the command is 'Register Write',
-            // arg1 is the register address and arg1 is the data
+                                                // arg1 is the register address and arg1 is the data
             break;
         default:
             cerr << "Error in Rhd2000Registers::createRhd2000Command: " <<
-                 "Only 'Register Write' commands take two arguments." << endl;
+                    "Only 'Register Write' commands take two arguments." << endl;
             return -1;
     }
 }
 
+
 // Create a list of 60 commands to program most RAM registers on a RHD2000 chip, read those values
 // back to confirm programming, read ROM registers, and (if calibrate == true) run ADC calibration.
 // Returns the length of the command list.
-int Rhd2000Registers::createCommandListRegisterConfig(vector<int>& commandList, bool calibrate)
+int Rhd2000Registers::createCommandListRegisterConfig(vector<int> &commandList, bool calibrate)
 {
     commandList.clear();    // if command list already exists, erase it and start a new one
 
@@ -792,17 +745,17 @@ int Rhd2000Registers::createCommandListRegisterConfig(vector<int>& commandList,
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
 
     // Program RAM registers
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  0, getRegisterValue(0)));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  1, getRegisterValue(1)));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  2, getRegisterValue(2)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  0, getRegisterValue( 0)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  1, getRegisterValue( 1)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  2, getRegisterValue( 2)));
     // Don't program Register 3 (MUX Load, Temperature Sensor, and Auxiliary Digital Output);
     // control temperature sensor in another command stream
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  4, getRegisterValue(4)));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  5, getRegisterValue(5)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  4, getRegisterValue( 4)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  5, getRegisterValue( 5)));
     // Don't program Register 6 (Impedance Check DAC) here; create DAC waveform in another command stream
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  7, getRegisterValue(7)));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  8, getRegisterValue(8)));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  9, getRegisterValue(9)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  7, getRegisterValue( 7)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  8, getRegisterValue( 8)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite,  9, getRegisterValue( 9)));
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 10, getRegisterValue(10)));
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 11, getRegisterValue(11)));
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 12, getRegisterValue(12)));
@@ -857,20 +810,21 @@ int Rhd2000Registers::createCommandListRegisterConfig(vector<int>& commandList,
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 17));
 
     // Optionally, run ADC calibration (should only be run once after board is plugged in)
-    if (calibrate)
-    {
+    if (calibrate) {
         commandList.push_back(createRhd2000Command(Rhd2000CommandCalibrate));
-    }
-    else
-    {
+    } else {
         commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
     }
 
-    // End with a few dummy commands
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
-    commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
+    // Added in Version 1.2:
+    // Program amplifier 31-63 power up/down registers in case a RHD2164 is connected
+    // Note: We don't read these registers back, since they are only 'visible' on MISO B.
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 18, getRegisterValue(18)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 19, getRegisterValue(19)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 20, getRegisterValue(20)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 21, getRegisterValue(21)));
+
+    // End with a dummy command
     commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63));
 
 
@@ -888,7 +842,7 @@ int Rhd2000Registers::createCommandListRegisterConfig(vector<int>& commandList,
 // different RAM banks, and the appropriate command list selected at the right time.
 //
 // Returns the length of the command list.
-int Rhd2000Registers::createCommandListTempSensor(vector<int>& commandList)
+int Rhd2000Registers::createCommandListTempSensor(vector<int> &commandList)
 {
     int i;
 
@@ -939,8 +893,7 @@ int Rhd2000Registers::createCommandListTempSensor(vector<int>& commandList)
     commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34));     // sample AuxIn3
     commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 48));     // sample Supply Voltage Sensor
 
-    for (i = 0; i < 8; ++i)
-    {
+    for (i = 0; i < 8; ++i) {
         commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32));     // sample AuxIn1
         commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33));     // sample AuxIn2
         commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34));     // sample AuxIn3
@@ -950,11 +903,80 @@ int Rhd2000Registers::createCommandListTempSensor(vector<int>& commandList)
     return commandList.size();
 }
 
+// Create a list of 60 commands to update Register 3 (controlling the auxiliary digital ouput
+// pin) every sampling period.
+//
+// Since this command list consists of writing to Register 3, it also sets the state of the
+// on-chip temperature sensor.  The temperature sensor settings are therefore changed throughout
+// this command list to coordinate with the 60-command list generated by createCommandListTempSensor().
+//
+// Returns the length of the command list.
+int Rhd2000Registers::createCommandListUpdateDigOut(vector<int> &commandList)
+{
+    int i;
+
+    commandList.clear();    // if command list already exists, erase it and start a new one
+
+    tempEn = 1;
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    tempS1 = tempEn;
+    tempS2 = 0;
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    tempS1 = tempEn;
+    tempS2 = tempEn;
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    tempS1 = 0;
+    tempS2 = tempEn;
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    tempS1 = 0;
+    tempS2 = 0;
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+
+    for (i = 0; i < 8; ++i) {
+        commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+        commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+        commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+        commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3)));
+    }
+
+    return commandList.size();
+}
+
 // Create a list of up to 1024 commands to generate a sine wave of particular frequency (in Hz) and
 // amplitude (in DAC steps, 0-128) using the on-chip impedance testing voltage DAC.  If frequency is set to zero,
 // a DC baseline waveform is created.
 // Returns the length of the command list.
-int Rhd2000Registers::createCommandListZcheckDac(vector<int>& commandList, double frequency, double amplitude)
+int Rhd2000Registers::createCommandListZcheckDac(vector<int> &commandList, double frequency, double amplitude)
 {
     int i, period, value;
     double t;
@@ -962,49 +984,34 @@ int Rhd2000Registers::createCommandListZcheckDac(vector<int>& commandList, doubl
 
     commandList.clear();    // if command list already exists, erase it and start a new one
 
-    if (amplitude < 0.0 || amplitude > 128.0)
-    {
+    if (amplitude < 0.0 || amplitude > 128.0) {
         cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Amplitude out of range." << endl;
         return -1;
     }
-    if (frequency < 0.0)
-    {
+    if (frequency < 0.0) {
         cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Negative frequency not allowed." << endl;
         return -1;
-    }
-    else if (frequency > sampleRate / 4.0)
-    {
+    } else if (frequency > sampleRate / 4.0) {
         cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: " <<
-             "Frequency too high relative to sampling rate." << endl;
+                "Frequency too high relative to sampling rate." << endl;
         return -1;
     }
-    if (frequency == 0.0)
-    {
-        for (i = 0; i < MaxCommandLength; ++i)
-        {
+    if (frequency == 0.0) {
+        for (i = 0; i < MaxCommandLength; ++i) {
             commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 6, 128));
         }
-    }
-    else
-    {
+    } else {
         period = (int) floor(sampleRate / frequency + 0.5);
-        if (period > MaxCommandLength)
-        {
+        if (period > MaxCommandLength) {
             cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Frequency too low." << endl;
             return -1;
-        }
-        else
-        {
+        } else {
             t = 0.0;
-            for (i = 0; i < period; ++i)
-            {
+            for (i = 0; i < period; ++i) {
                 value = (int) floor(amplitude * sin(2 * Pi * frequency * t) + 128.0 + 0.5);
-                if (value < 0)
-                {
+                if (value < 0) {
                     value = 0;
-                }
-                else if (value > 255)
-                {
+                } else if (value > 255) {
                     value = 255;
                 }
                 commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 6, value));
diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000registers.h b/Source/Processors/DataThreads/rhythm-api/rhd2000registers.h
index 74ee25e89bc8b6f698150193fe1c5672200db81d..992f2b68de38b5f9ec4bfdaddda6f030f5fb0beb 100755
--- a/Source/Processors/DataThreads/rhythm-api/rhd2000registers.h
+++ b/Source/Processors/DataThreads/rhythm-api/rhd2000registers.h
@@ -3,9 +3,9 @@
 //
 // Intan Technoloies RHD2000 Rhythm Interface API
 // Rhd2000Registers Class Header File
-// Version 1.0 (14 January 2013)
+// Version 1.4 (26 February 2014)
 //
-// Copyright (c) 2013 Intan Technologies LLC
+// Copyright (c) 2013-2014 Intan Technologies LLC
 //
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors be held liable for any damages arising from the
@@ -49,15 +49,13 @@ public:
     void enableZcheck(bool enabled);
     void setZcheckDacPower(bool enabled);
 
-    enum ZcheckCs
-    {
+    enum ZcheckCs {
         ZcheckCs100fF,
         ZcheckCs1pF,
         ZcheckCs10pF
     };
 
-    enum ZcheckPolarity
-    {
+    enum ZcheckPolarity {
         ZcheckPositiveInput,
         ZcheckNegativeInput
     };
@@ -75,12 +73,12 @@ public:
     double setUpperBandwidth(double upperBandwidth);
     double setLowerBandwidth(double lowerBandwidth);
 
-    int createCommandListRegisterConfig(vector<int>& commandList, bool calibrate);
-    int createCommandListTempSensor(vector<int>& commandList);
-    int createCommandListZcheckDac(vector<int>& commandList, double frequency, double amplitude);
+    int createCommandListRegisterConfig(vector<int> &commandList, bool calibrate);
+    int createCommandListTempSensor(vector<int> &commandList);
+    int createCommandListUpdateDigOut(vector<int> &commandList);
+    int createCommandListZcheckDac(vector<int> &commandList, double frequency, double amplitude);
 
-    enum Rhd2000CommandType
-    {
+    enum Rhd2000CommandType {
         Rhd2000CommandConvert,
         Rhd2000CommandCalibrate,
         Rhd2000CommandCalClear,