/* ------------------------------------------------------------------ This file is part of the Open Ephys GUI Copyright (C) 2012 Open Ephys ------------------------------------------------------------------ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "FPGAThread.h" FPGAThread::FPGAThread(SourceNode* sn) : DataThread(sn), isRunning(false), numchannels(32), m_u32SegmentSize(1048576) { // Initialize the FPGA with our configuration bitfile. printf("New device created.\n"); const char* bitfilename = "./pipetest.bit"; printf("---- Opal Kelly ---- PipeTest Application v1.0 ----\n"); if (FALSE == okFrontPanelDLL_LoadLib(NULL)) { printf("FrontPanel DLL could not be loaded.\n"); } okFrontPanelDLL_GetVersion(dll_date, dll_time); printf("FrontPanel DLL loaded. Built: %s %s\n", dll_date, dll_time); dev = new okCFrontPanel; strncpy(bitfile, bitfilename, 128); if (!initializeFPGA(dev, bitfile)) { printf("FPGA could not be initialized.\n"); } Ndatabytes = numchannels*3; std::cout << "FPGA interface initialized." << std::endl; std::cout << "DataBuffer address is " << dataBuffer << std::endl; dataBuffer = new DataBuffer(32, 10000); std::cout << "DataBuffer address is " << dataBuffer << std::endl; //deviceFound = true; //startThread(); } FPGAThread::~FPGAThread() { std::cout << "FPGA interface destroyed." << std::endl; // probably not the best way to do this: deleteAndZero(dataBuffer); deleteAndZero(dev); } bool FPGAThread::startAcquisition() { startThread(); //isTransmitting = true; return true; } bool FPGAThread::stopAcquisition() { if (isThreadRunning()) { signalThreadShouldExit(); } return true; } bool FPGAThread::updateBuffer() { dev->ReadFromPipeOut(0xA0, sizeof(pBuffer), pBuffer); int j = 0; while (j < sizeof(pBuffer)) { // look for timecode block (6 bytes) if ( (pBuffer[j] & 1) && (pBuffer[j+1] & 1) && (pBuffer[j+2] & 1) && (pBuffer[j+3] & 1) && (pBuffer[j+4] & 1) && (pBuffer[j+5] & 1) && (j+5+Ndatabytes <= sizeof(pBuffer)) ) // indicated by last bit being 1 { //read 6 bytes, assemble to 6*7 = 42 bits, arranged in 6 bytes char timecode[6]; // 1st byte throw out last bit of each byte and just concatenate the other bytes in ascending order timecode[0] = (pBuffer[j] >> 1) | ((pBuffer[j+1] >> 1) << 7); // 2nd byte timecode[1] = (pBuffer[j+1] >> 2) | ((pBuffer[j+2] >> 1) << 6); // 3rd byte timecode[2] = (pBuffer[j+2] >> 3) | ((pBuffer[j+3] >> 1) << 5); // 4th byte timecode[3] = (pBuffer[j+3] >> 4) | ((pBuffer[j+4] >> 1) << 4); // 5th byte timecode[4] = (pBuffer[j+4] >> 5) | ((pBuffer[j+5] >> 1) << 3); // 6th byte timecode[5] = (pBuffer[j+5] >> 6); j += 6; //move cursor to 1st data byte // loop through sample data and condense from 3 bytes to 2 bytes char hi; char lo; for (int n = 0; n < numchannels ; n++) { // last bit of first 2 is zero, replace with bits 1 and 2 from 3rd byte hi = (pBuffer[j]) | ((( pBuffer[j+2] >> 2) & ~(1<<6)) & ~(1<<7)) ; lo = (pBuffer[j+1]) | ((( pBuffer[j+2] >> 1) & ~(1<<1)) & ~(1<<7)) ; j += 3; //thisSample[n] = float( hi - 256)/256; uint16 samp = ((hi << 8) + lo); thisSample[n] = (float(samp) - 32768.0f)/92768.0f; } dataBuffer->addToBuffer(thisSample,1); } j++; // keep scanning for timecodes } return true; } bool FPGAThread::initializeFPGA(okCFrontPanel *dev, char *bitfile) { if (okCFrontPanel::NoError != dev->OpenBySerial()) { delete dev; printf("Device could not be opened. Is one connected?\n"); return(NULL); } printf("Found a device: %s\n", dev->GetBoardModelString(dev->GetBoardModel()).c_str()); dev->LoadDefaultPLLConfiguration(); // Get some general information about the XEM. std::string str; printf("Device firmware version: %d.%d\n", dev->GetDeviceMajorVersion(), dev->GetDeviceMinorVersion()); str = dev->GetSerialNumber(); printf("Device serial number: %s\n", str.c_str()); str = dev->GetDeviceID(); printf("Device device ID: %s\n", str.c_str()); // Download the configuration file. if (okCFrontPanel::NoError != dev->ConfigureFPGA(bitfile)) { printf("FPGA configuration failed.\n"); return(false); } // Check for FrontPanel support in the FPGA configuration. if (dev->IsFrontPanelEnabled()) printf("FrontPanel support is enabled.\n"); else printf("FrontPanel support is not enabled.\n"); return(true); dev->SetWireInValue(0x00, 1<<2); // set reset bit in cmd wire to 1 and back to 0 dev->UpdateWireIns(); dev->SetWireInValue(0x00, 0<<2); dev->UpdateWireIns(); }