Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
#include "NIDAQmxInterface.h"
/* initialize tasks in DAQmx interface */
/*Indirection for C function pointer to method pointer */
int32 CVICALLBACK inputCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData) {
NIDAQmxInterface * this_ = reinterpret_cast<NIDAQmxInterface*>(callbackData);
return this_->FcnCbckDetectDI(taskHandle, signalID);
}
/*Indirection for C function pointer to method pointer */
int32 CVICALLBACK pulldownTimerCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData) {
NIDAQmxInterface * this_ = reinterpret_cast<NIDAQmxInterface*>(callbackData);
return this_->FcnCbckTriggerStopDO(taskHandle, signalID);
}
NIDAQmxInterface::NIDAQmxInterface(QObject* parent) : QObject(parent)
{
daq = new DAQmxEngine();
}
NIDAQmxInterface::~NIDAQmxInterface()
{
delete daq;
}
void NIDAQmxInterface::DAQmxInitializeInterface()
{
/* initialize daq pointer */
DAQmxSetDefaultEngine();
/* configure digital read error task */
errorCheck(DAQmxCreateTask("DigError", &daq->di_error));
errorCheck(DAQmxCreateDIChan(daq->di_error, "Dev1/port2", "", DAQmx_Val_ChanForAllLines));
DAQmxReadErrorPort();
/* configure digital read task */
errorCheck(DAQmxCreateTask("DigIn", &daq->di_port));
errorCheck(DAQmxCreateDIChan(daq->di_port, "Dev1/port0", "", DAQmx_Val_ChanForAllLines));
errorCheck(DAQmxCfgChangeDetectionTiming(daq->di_port, "Dev1/port0/line2,Dev1/port0/line3,Dev1/port0/line6", "Dev1/port0/line2,Dev1/port0/line3,Dev1/port0/line6", DAQmx_Val_ContSamps, 1));
//errorCheck(DAQmxCfgChangeDetectionTiming(daq->di_port, "Dev1/port0/line2,Dev1/port0/line6", "Dev1/port0/line2,Dev1/port0/line6", DAQmx_Val_ContSamps, 1));
errorCheck(DAQmxRegisterSignalEvent(daq->di_port, DAQmx_Val_ChangeDetectionEvent, 0, inputCallbackWrapper, this));
/* configure digital write task */
errorCheck(DAQmxCreateTask("DigOut", &daq->do_port));
errorCheck(DAQmxCreateDOChan(daq->do_port, "Dev1/port1", "", DAQmx_Val_ChanForAllLines));
/* configure digital internal clock task */
errorCheck(DAQmxCreateTask("DigClk", &daq->do_clk));
//errorCheck(DAQmxCreateCOPulseChanTime(daq->do_clk, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0, 0.05, DO_PULSE_WIDTH));
errorCheck(DAQmxCreateCOPulseChanTime(daq->do_clk, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0, 0.05, 0.08));
errorCheck(DAQmxCfgImplicitTiming(daq->do_clk, DAQmx_Val_FiniteSamps, 1));
errorCheck(DAQmxRegisterDoneEvent(daq->do_clk, 0, pulldownTimerCallbackWrapper, this));
/* start custom task */
DAQmxStartCustomTask(daq->di_port);
return;
}
/* allocate engine pointer */
void NIDAQmxInterface::DAQmxSetDefaultEngine()
{
/* ports TaskHandle */
daq->di_port = 0;
daq->di_error = 0;
daq->do_port = 0;
/* ports states uInt8 */
daq->di_bit_now = DAQ_PORT_NULL;
daq->di_bit_prev = DAQ_PORT_NULL;
daq->do_bit_wrt = DAQ_PORT_NULL;
daq->do_bit_qry = DAQ_PORT_NULL;
/* event counters uInt32 */
daq->di_cntr_lick = 0;
daq->di_cntr_frame = 0;
daq->di_cntr_imaq = 0;
daq->di_cntr_cameraTrigger = 0;
return;
}
/* read error port */
void NIDAQmxInterface::DAQmxReadErrorPort()
{
int32 read = 0;
uInt8 port_bit = DAQ_PORT_NULL;
/* start task */
DAQmxStartCustomTask(daq->di_error);
/* read port */
if (daq->di_error != 0)
errorCheck(DAQmxReadDigitalU8(daq->di_error, 1, 10.0, DAQmx_Val_GroupByChannel, &port_bit, 1, &read, NULL));
/* stop task */
DAQmxStopCustomTask(daq->di_error);
/* check for active error signals */
if (read)
{
if ((port_bit & DAQ_PORT_DE_MONITOR) == DAQ_PORT_DE_MONITOR)
{
fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tMONITOR failed!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: Monitor read error on NIDAQ", 0, 0, timeString));
return;
}
if ((port_bit & DAQ_PORT_DE_AIR) == DAQ_PORT_DE_AIR)
{
fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tAIR pump failed!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: Air read error on NIDAQ", 0, 0, timeString));
return;
}
if ((port_bit & DAQ_PORT_DE_WATER) == DAQ_PORT_DE_WATER)
{
fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tWATER pump failed!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: Water read error on NIDAQ", 0, 0, timeString));
return;
}
}
return;
}
/* destroy tasks in DAQmx interface */
void NIDAQmxInterface::DAQmxDestroyInterface()
{
/* check if task is digital output task is done */
errorCheck(DAQmxWaitUntilTaskDone(daq->do_clk, -1));
/* stop tasks */
DAQmxStopCustomTask(daq->di_port);
DAQmxStopCustomTask(daq->do_port);
DAQmxStopCustomTask(daq->do_clk);
DAQmxStopCustomTask(daq->di_error);
/* clear tasks */
errorCheck(DAQmxClearTask(daq->di_port));
daq->di_port = 0;
errorCheck(DAQmxClearTask(daq->do_port));
daq->do_port = 0;
errorCheck(DAQmxClearTask(daq->do_clk));
daq->do_clk = 0;
errorCheck(DAQmxClearTask(daq->di_error));
daq->di_error = 0;
return;
}
/* Start custom tasks */
void NIDAQmxInterface::DAQmxStartCustomTask(TaskHandle taskHandle)
{
bool32 done = false;
if (taskHandle != 0)
{
/* check if task is already active */
errorCheck(DAQmxIsTaskDone(taskHandle, &done));
if (!done)
errorCheck(DAQmxStopTask(taskHandle));
/* start / re-start task */
errorCheck(DAQmxStartTask(taskHandle));
}
return;
}
/* Stop custom tasks */
void NIDAQmxInterface::DAQmxStopCustomTask(TaskHandle taskHandle)
{
bool32 done = false;
if (taskHandle != 0)
{
/* check if task is active */
errorCheck(DAQmxIsTaskDone(taskHandle, &done));
if (!done)
errorCheck(DAQmxStopTask(taskHandle));
}
return;
}
/* Trigger digital output */
void NIDAQmxInterface::DAQmxTriggerDO(uInt8 qry_port_bit, bool arm_timer)
{
if(!isPaused){
int32 written = 0;
bool32 done = TRUE;
/* flip query bit to switch on qry bit */
if (daq->do_port != 0)
{
daq->do_bit_wrt ^= qry_port_bit;
errorCheck(DAQmxWriteDigitalU8(daq->do_port, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->do_bit_wrt, &written, NULL));
}
/* check for error */
if (written == 0)
{
fprintf(stderr, "Error::NIDAQmxInterface/DAQmxTriggerDO:\n\tfailed to write to DO port!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: unable to TriggerDO on NIDAQ", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit, timeString));
return;
}
/* arm time out if required */
if ((daq->do_clk != 0) & (arm_timer == TRUE))
{
errorCheck(DAQmxIsTaskDone(daq->do_clk, &done));
daq->do_bit_qry = (done) ? qry_port_bit : (daq->do_bit_qry | qry_port_bit);
errorCheck(DAQmxStopTask(daq->do_clk));
errorCheck(DAQmxStartTask(daq->do_clk));
}
/* log trigger */
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("TRIGGER", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit, timeString));
}
return;
}
void NIDAQmxInterface::DAQmxSetDO(uInt8 qry_port_bit, bool arm_timer, bool isSet)
{
if(!isPaused){
int32 written = 0;
bool32 done = TRUE;
/* flip query bit to switch on qry bit */
if (daq->do_port != 0)
{
if(isSet){
daq->do_bit_wrt |= (1 << (qry_port_bit-1));
}else{
daq->do_bit_wrt &= ~(1 << (qry_port_bit-1));
}
errorCheck(DAQmxWriteDigitalU8(daq->do_port, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->do_bit_wrt, &written, NULL));
}
/* check for error */
if (written == 0)
{
fprintf(stderr, "Error::NIDAQmxInterface/DAQmxTriggerDO:\n\tfailed to write to DO port!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: unable to SetDO on NIDAQ", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit, timeString));
return;
}
/* arm time out if required */
if ((daq->do_clk != 0) & (arm_timer == TRUE))
{
errorCheck(DAQmxIsTaskDone(daq->do_clk, &done));
daq->do_bit_qry = (done) ? qry_port_bit : (daq->do_bit_qry | qry_port_bit);
errorCheck(DAQmxStopTask(daq->do_clk));
errorCheck(DAQmxStartTask(daq->do_clk));
}
/* log trigger */
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("TRIGGER", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit, timeString));
}
return;
}
/* Detect Input Callback */
int32 CVICALLBACK NIDAQmxInterface::FcnCbckDetectDI(TaskHandle taskHandle, int32 signalID)
{
if(!isPaused){
int32 read = 0;
if (taskHandle != 0)
errorCheck(DAQmxReadDigitalU8(taskHandle, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->di_bit_now, 1, &read, NULL));
if (read)
{
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
/* CAMERATRIGGER condition, line 3 changes from 1 to 0 */
if (((daq->di_bit_prev & DAQ_PORT_DI_CAMERATRIGGER) == DAQ_PORT_DI_CAMERATRIGGER) & ((daq->di_bit_now & DAQ_PORT_DI_CAMERATRIGGER) == DAQ_PORT_NULL))
{
daq->di_cntr_cameraTrigger++;
emit(writeToLogFile("CAMERATRIGGER", DAQ_PORT_DI_CAMERATRIGGER, daq->di_cntr_cameraTrigger, timeString));
}
/* FRAME condition, line 2 changes from 1 to 0 */
if (((daq->di_bit_prev & DAQ_PORT_DI_FRAME) == DAQ_PORT_DI_FRAME) & ((daq->di_bit_now & DAQ_PORT_DI_FRAME) == DAQ_PORT_NULL))
{
daq->di_cntr_frame++;
emit(writeToLogFile("FRAME", daq->di_cntr_imaq, daq->di_cntr_frame, timeString));
}
/* LICK condition, line 6 changes from 0 to 1 */
if (((daq->di_bit_prev & DAQ_PORT_DI_LICK) == DAQ_PORT_NULL) & ((daq->di_bit_now & DAQ_PORT_DI_LICK) == DAQ_PORT_DI_LICK))
{
daq->di_cntr_lick++;
emit(writeToLogFile("LICK", DAQ_PORT_DI_LICK, daq->di_cntr_lick, timeString));
/* every N licks give a reward */
if ((daq->di_cntr_lick % licksToReward) == 0){
DAQmxTriggerDO(DAQ_PORT_DO_WATER, TRUE);
qDebug()<<"Water reward!";
}
}
/* update bit history */
daq->di_bit_prev = daq->di_bit_now;
}
}
return 0;
}
/* Timer Digital Out is Done */
int32 CVICALLBACK NIDAQmxInterface::FcnCbckTriggerStopDO(TaskHandle taskHandle, int32 signalID)
{
if(!isPaused){
int32 written = 0;
/* flip query bit, to switch off pulse */
if (daq->do_port != 0)
{
daq->do_bit_wrt ^= daq->do_bit_qry;
errorCheck(DAQmxWriteDigitalU8(daq->do_port, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->do_bit_wrt, &written, NULL));
}
/* check for error */
if (written == 0)
{
fprintf(stderr, "Error::NIDAQmxInterface/FcnCbckTriggerStopDO: failed to write to DO port!\n");
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("ERROR: unable to set timeout for NIDAQ", 0, 0, timeString));
return -1;
}
/* log trigger */
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("TRIGGER", daq->do_bit_qry, (daq->do_bit_qry & daq->do_bit_wrt) == daq->do_bit_qry, timeString));
}
return 0;
}
bool NIDAQmxInterface::errorCheck(int32 functionReturnValue)
{
if((functionReturnValue) < 0){
char errBuffer[2048];
DAQmxGetExtendedErrorInfo(errBuffer, 2048);
qDebug() << errBuffer;
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile(QString("ERROR: ").append(errBuffer), 0, 0, timeString));
//fprintf(stderr, "DAQmxError: %s\n Calling: %s\n", errBuffer, functionReturnValue);
return true;
}else{
return false;
}
}