diff --git a/AudioGameGUI.pro b/AudioGameGUI.pro index 056b1c8..d465701 100644 --- a/AudioGameGUI.pro +++ b/AudioGameGUI.pro @@ -8,15 +8,18 @@ QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 -QT += axcontainer -TYPELIBS = $$system(dumpcpp -getfile {D323A622-1D13-11D4-8858-444553540000}) - -isEmpty(TYPELIBS) { - message("TDT library not found!") -} else { - TYPELIBS = $$system(dumpcpp {D323A622-1D13-11D4-8858-444553540000}) - HEADERS += rpcoxlib.h - SOURCES += rpcoxlib.cpp + +win32 { + QT += axcontainer + TYPELIBS = $$system(dumpcpp -getfile {D323A622-1D13-11D4-8858-444553540000}) + + isEmpty(TYPELIBS) { + message("TDT library not found!") + } else { + TYPELIBS = $$system(dumpcpp {D323A622-1D13-11D4-8858-444553540000}) + HEADERS += rpcoxlib.h + SOURCES += rpcoxlib.cpp + } } TARGET = AudioGameGUI @@ -40,9 +43,6 @@ HEADERS += \ TDTInterface.h \ trialseq.h -LIBS += -L"C:\\Program Files (x86)\\National Instruments\\NI-DAQ\\DAQmx ANSI C Dev\\lib\\msvc" \ - -lNIDAQmx - #LIBS += -L"C:\\TDT\\lib64" \ # -lRPco @@ -50,3 +50,7 @@ FORMS += mainwindow.ui \ timerdialog.ui DISTFILES += + + +LIBS += -L"C:\\Program Files (x86)\\National Instruments\\Shared\\ExternalCompilerSupport\\C\\lib64\\msvc" \ + -lNIDAQmx diff --git a/AudioGameGUI.pro.user b/AudioGameGUI.pro.user index 4a014e4..9375077 100644 --- a/AudioGameGUI.pro.user +++ b/AudioGameGUI.pro.user @@ -1,6 +1,6 @@ - + ProjectExplorer.Project.ActiveTarget diff --git a/Mainwindow.cpp b/Mainwindow.cpp index 725f877..126dc1e 100644 --- a/Mainwindow.cpp +++ b/Mainwindow.cpp @@ -40,8 +40,12 @@ MainWindow::MainWindow(QWidget *parent) : ui->lineEdit_licksToReward->setValidator(intValidator); ui->lineEdit_iti->setValidator(doubleValidator); - connect(&smc, SIGNAL(statusMessage(QString)), this, SLOT(onStatusMessage(QString))); + ui->lineEdit_fileNegative->setText("C:/Users/superuser.D-01477/Desktop/attentionGame/20160812_AttentionGame/20160812_AttentionGame/Audio/negative_state.rcx"); + ui->lineEdit_filePositive->setText("C:/Users/superuser.D-01477/Desktop/attentionGame/20160812_AttentionGame/20160812_AttentionGame/Audio/positive_state.rcx"); + + connect(&smc, SIGNAL(statusMessage(QString)), this, SLOT(onStatusMessage(QString))); + connect(&smc, SIGNAL(terminated()), this, SLOT(onStateMachineTerminated())); } MainWindow::~MainWindow() @@ -78,6 +82,8 @@ void MainWindow::on_pushButton_Run_clicked() settings.soundDurationNegative = ui->lineEdit_soundDurationNegative->text().toDouble(); settings.userReaction = userReaction; settings.trialSequence = TrialSeq::generateTrialSequence(sorting, ui->lineEdit_repeatPositive->text().toInt(), ui->lineEdit_repeatNegative->text().toInt()); + settings.fileNameNegative = ui->lineEdit_filePositive->text(); + settings.fileNamePositive = ui->lineEdit_filePositive->text(); if(ui->checkBox_itiExternal->isChecked()){ qDebug()<<"Using iti from file"; @@ -174,7 +180,7 @@ void MainWindow::on_pushButton_selectFilePositive_clicked() appSettings.setValue(DEFAULT_DIR_KEY, currentDir.absoluteFilePath(selectedPositiveFileName)); - ui->lineEdit_selectFilePositive->setText(selectedPositiveFileName); + ui->lineEdit_filePositive->setText(selectedPositiveFileName); } } @@ -189,7 +195,7 @@ void MainWindow::on_pushButton_selectFileNegative_clicked() appSettings.setValue(DEFAULT_DIR_KEY, currentDir.absoluteFilePath(selectedNegativeFileName)); - ui->lineEdit_selectFileNegative->setText(selectedNegativeFileName); + ui->lineEdit_fileNegative->setText(selectedNegativeFileName); } } @@ -213,6 +219,11 @@ void MainWindow::on_lineEdit_preImaq_editingFinished() updateIti(); } +void MainWindow::onStateMachineTerminated() +{ + ui->pushButton_Run->setText("Run"); +} + void MainWindow::onStatusMessage(QString statusMessage) { ui->statusBar->showMessage(statusMessage); diff --git a/Mainwindow.h b/Mainwindow.h index 19de4a7..8d28230 100644 --- a/Mainwindow.h +++ b/Mainwindow.h @@ -40,6 +40,7 @@ private slots: void on_lineEdit_iti_editingFinished(); void on_lineEdit_preImaq_editingFinished(); + void onStateMachineTerminated(); void onStatusMessage(QString statusMessage); diff --git a/NIDAQmxInterface.cpp b/NIDAQmxInterface.cpp index f6f50b2..0454b6b 100644 --- a/NIDAQmxInterface.cpp +++ b/NIDAQmxInterface.cpp @@ -1,10 +1,21 @@ #include "NIDAQmxInterface.h" -#include "C:\Program Files (x86)\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h" - /* initialize tasks in DAQmx interface */ + +/*Indirection for C function pointer to method pointer */ +int32 CVICALLBACK ChangeDetectionCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData) { + NIDAQmxInterface * this_ = reinterpret_cast(callbackData); + return this_->FcnCbckDetectDI(taskHandle, signalID, callbackData); +} +/*Indirection for C function pointer to method pointer */ +int32 CVICALLBACK ChangeTriggerStopCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData) { + NIDAQmxInterface * this_ = reinterpret_cast(callbackData); + return this_->FcnCbckTriggerStopDO(taskHandle, signalID, callbackData); +} + + NIDAQmxInterface::NIDAQmxInterface() { - + daq = new DAQmxEngine(); } void NIDAQmxInterface::DAQmxInitializeInterface() @@ -13,32 +24,34 @@ void NIDAQmxInterface::DAQmxInitializeInterface() DAQmxSetDefaultEngine(); /* configure digital read error task */ - DAQmxCreateTask("DigError", &daq->di_error); - //DAQmxErrChk(DAQmxCreateTask("DigError", &daq->di_error)); -// DAQmxErrChk(DAQmxCreateDIChan(daq->di_error, "Dev1/port2", "", DAQmx_Val_ChanForAllLines)); -// DAQmxReadErrorPort(); + DAQmxErrChk(DAQmxCreateTask("DigError", &daq->di_error)); + DAQmxErrChk(DAQmxCreateDIChan(daq->di_error, "Dev1/port2", "", DAQmx_Val_ChanForAllLines)); + DAQmxReadErrorPort(); -// /* configure digital read task */ -// DAQmxErrChk(DAQmxCreateTask("DigIn", &daq->di_port)); -// DAQmxErrChk(DAQmxCreateDIChan(daq->di_port, "Dev1/port0", "", DAQmx_Val_ChanForAllLines)); -// DAQmxErrChk(DAQmxCfgChangeDetectionTiming(daq->di_port, "Dev1/port0/line2,Dev1/port0/line6", "Dev1/port0/line2,Dev1/port0/line6", DAQmx_Val_ContSamps, 1)); -// //DAQmxErrChk(DAQmxRegisterSignalEvent(daq->di_port, DAQmx_Val_ChangeDetectionEvent, 0, FcnCbckDetectDI, daq)); + /* configure digital read task */ + DAQmxErrChk(DAQmxCreateTask("DigIn", &daq->di_port)); + DAQmxErrChk(DAQmxCreateDIChan(daq->di_port, "Dev1/port0", "", DAQmx_Val_ChanForAllLines)); + DAQmxErrChk(DAQmxCfgChangeDetectionTiming(daq->di_port, "Dev1/port0/line2,Dev1/port0/line6", "Dev1/port0/line2,Dev1/port0/line6", DAQmx_Val_ContSamps, 1)); + DAQmxErrChk(DAQmxRegisterSignalEvent(daq->di_port, DAQmx_Val_ChangeDetectionEvent, 0, ChangeDetectionCallbackWrapper, daq)); -// /* configure digital write task */ -// DAQmxErrChk(DAQmxCreateTask("DigOut", &daq->do_port)); -// DAQmxErrChk(DAQmxCreateDOChan(daq->do_port, "Dev1/port1", "", DAQmx_Val_ChanForAllLines)); -// /* configure digital internal clock task */ -// DAQmxErrChk(DAQmxCreateTask("DigClk", &daq->do_clk)); -// DAQmxErrChk(DAQmxCreateCOPulseChanTime(daq->do_clk, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0, 0.05, DO_PULSE_WIDTH)); -// DAQmxErrChk(DAQmxCfgImplicitTiming(daq->do_clk, DAQmx_Val_FiniteSamps, 1)); -// //DAQmxErrChk(DAQmxRegisterDoneEvent(daq->do_clk, 0, FcnCbckTriggerStopDO, daq)); + /* configure digital write task */ + DAQmxErrChk(DAQmxCreateTask("DigOut", &daq->do_port)); + DAQmxErrChk(DAQmxCreateDOChan(daq->do_port, "Dev1/port1", "", DAQmx_Val_ChanForAllLines)); -// /* initialize query performance timer QPC */ -// //QPCInitialize(); + /* configure digital internal clock task */ + DAQmxErrChk(DAQmxCreateTask("DigClk", &daq->do_clk)); + //DAQmxErrChk(DAQmxCreateCOPulseChanTime(daq->do_clk, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0, 0.05, DO_PULSE_WIDTH)); + DAQmxErrChk(DAQmxCreateCOPulseChanTime(daq->do_clk, "Dev1/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0, 0.05, 0.08)); + DAQmxErrChk(DAQmxCfgImplicitTiming(daq->do_clk, DAQmx_Val_FiniteSamps, 1)); -// /* start custom task */ -// DAQmxStartCustomTask(daq->di_port); + DAQmxErrChk(DAQmxRegisterDoneEvent(daq->do_clk, 0, ChangeTriggerStopCallbackWrapper, daq)); + + /* initialize query performance timer QPC */ + //QPCInitialize(); + + /* start custom task */ + DAQmxStartCustomTask(daq->di_port); return; } @@ -86,87 +99,87 @@ void NIDAQmxInterface::DAQmxSetDefaultEngine() /* 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) -// DAQmxErrChk(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"); -// exit(EXIT_FAILURE); -// } - -// if ((port_bit & DAQ_PORT_DE_AIR) == DAQ_PORT_DE_AIR) -// { -// fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tAIR pump failed!\n"); -// exit(EXIT_FAILURE); -// } - -// if ((port_bit & DAQ_PORT_DE_WATER) == DAQ_PORT_DE_WATER) -// { -// fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tWATER pump failed!\n"); -// exit(EXIT_FAILURE); -// } -// } - -// return; + int32 read = 0; + uInt8 port_bit = DAQ_PORT_NULL; + + /* start task */ + DAQmxStartCustomTask(daq->di_error); + + /* read port */ + if (daq->di_error != 0) + DAQmxErrChk(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"); + exit(EXIT_FAILURE); + } + + if ((port_bit & DAQ_PORT_DE_AIR) == DAQ_PORT_DE_AIR) + { + fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tAIR pump failed!\n"); + exit(EXIT_FAILURE); + } + + if ((port_bit & DAQ_PORT_DE_WATER) == DAQ_PORT_DE_WATER) + { + fprintf(stderr, "DAQmxError:NIDAQmxInterface/DAQmxReadErrorPort:\n\tWATER pump failed!\n"); + exit(EXIT_FAILURE); + } + } + + return; } /* destroy tasks in DAQmx interface */ void NIDAQmxInterface::DAQmxDestroyInterface() { -// /* check if task is digital output task is done */ -// DAQmxErrChk(DAQmxWaitUntilTaskDone(daq->do_clk, -1)); - -// /* stop tasks */ -// DAQmxStopCustomTask(daq->di_port); -// DAQmxStopCustomTask(daq->do_port); -// DAQmxStopCustomTask(daq->do_clk); - -// /* clear tasks */ -// DAQmxErrChk(DAQmxClearTask(daq->di_port)); -// daq->di_port = 0; -// DAQmxErrChk(DAQmxClearTask(daq->do_port)); -// daq->do_port = 0; -// DAQmxErrChk(DAQmxClearTask(daq->do_clk)); -// daq->do_clk = 0; - -// /* close file */ -// if (daq->fp_log) -// fclose(daq->fp_log); - -// return; + /* check if task is digital output task is done */ + DAQmxErrChk(DAQmxWaitUntilTaskDone(daq->do_clk, -1)); + + /* stop tasks */ + DAQmxStopCustomTask(daq->di_port); + DAQmxStopCustomTask(daq->do_port); + DAQmxStopCustomTask(daq->do_clk); + + /* clear tasks */ + DAQmxErrChk(DAQmxClearTask(daq->di_port)); + daq->di_port = 0; + DAQmxErrChk(DAQmxClearTask(daq->do_port)); + daq->do_port = 0; + DAQmxErrChk(DAQmxClearTask(daq->do_clk)); + daq->do_clk = 0; + + /* close file */ + if (daq->fp_log) + fclose(daq->fp_log); + + return; } /* Start custom tasks */ void NIDAQmxInterface::DAQmxStartCustomTask(TaskHandle taskHandle) { -// bool32 done = false; + bool32 done = false; -// if (taskHandle != 0) -// { -// /* check if task is already active */ -// DAQmxErrChk(DAQmxIsTaskDone(taskHandle, &done)); -// if (!done) -// DAQmxErrChk(DAQmxStopTask(taskHandle)); + if (taskHandle != 0) + { + /* check if task is already active */ + DAQmxErrChk(DAQmxIsTaskDone(taskHandle, &done)); + if (!done) + DAQmxErrChk(DAQmxStopTask(taskHandle)); -// /* start / re-start task */ -// DAQmxErrChk(DAQmxStartTask(taskHandle)); -// } + /* start / re-start task */ + DAQmxErrChk(DAQmxStartTask(taskHandle)); + } return; } @@ -174,52 +187,52 @@ void NIDAQmxInterface::DAQmxStartCustomTask(TaskHandle taskHandle) /* Stop custom tasks */ void NIDAQmxInterface::DAQmxStopCustomTask(TaskHandle taskHandle) { -// bool32 done = false; + bool32 done = false; -// if (taskHandle != 0) -// { -// /* check if task is active */ -// DAQmxErrChk(DAQmxIsTaskDone(taskHandle, &done)); -// if (!done) -// DAQmxErrChk(DAQmxStopTask(taskHandle)); -// } + if (taskHandle != 0) + { + /* check if task is active */ + DAQmxErrChk(DAQmxIsTaskDone(taskHandle, &done)); + if (!done) + DAQmxErrChk(DAQmxStopTask(taskHandle)); + } -// return; + return; } /* Trigger digital output */ void NIDAQmxInterface::DAQmxTriggerDO(uInt8 qry_port_bit, bool arm_timer) { -// 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; -// DAQmxErrChk(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"); -// exit(EXIT_FAILURE); -// } - -// /* arm time out if required */ -// if ((daq->do_clk != 0) & (arm_timer == TRUE)) -// { -// DAQmxErrChk(DAQmxIsTaskDone(daq->do_clk, &done)); -// daq->do_bit_qry = (done) ? qry_port_bit : (daq->do_bit_qry | qry_port_bit); -// DAQmxErrChk(DAQmxStopTask(daq->do_clk)); -// DAQmxErrChk(DAQmxStartTask(daq->do_clk)); -// } - -// /* log trigger */ -// DAQmxLogToFile(daq->fp_log, "TRIGGER", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit); - -// return; + 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; + DAQmxErrChk(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"); + exit(EXIT_FAILURE); + } + + /* arm time out if required */ + if ((daq->do_clk != 0) & (arm_timer == TRUE)) + { + + DAQmxErrChk(DAQmxIsTaskDone(daq->do_clk, &done)); + daq->do_bit_qry = (done) ? qry_port_bit : (daq->do_bit_qry | qry_port_bit); + DAQmxErrChk(DAQmxStopTask(daq->do_clk)); + DAQmxErrChk(DAQmxStartTask(daq->do_clk)); + } + /* log trigger */ + //DAQmxLogToFile(daq->fp_log, "TRIGGER", qry_port_bit, (qry_port_bit & daq->do_bit_wrt) == qry_port_bit); + + return; } /* log NIDAQmx events to file */ @@ -231,88 +244,89 @@ void NIDAQmxInterface::DAQmxLogToFile(FILE *fp, const char *msg, uInt32 id, uInt } /* Detect Input Callback */ -int32 CVICALLBACK NIDAQmxInterface::FcnCbckDetectDI(TaskHandle taskHandle, int32 signalID, void *callback_data) +int32 CVICALLBACK NIDAQmxInterface::FcnCbckDetectDI(TaskHandle taskHandle, int32 signalID, void* callbackData) { -// DAQmxEngine *daq = (DAQmxEngine *)callback_data; -// int32 read = 0; - -// if (taskHandle != 0) -// DAQmxErrChk(DAQmxReadDigitalU8(taskHandle, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->di_bit_now, 1, &read, NULL)); - -// if (read) -// { -// /* SHUTTER ON condition, SHUTTER line changes from 0 to 1 */ -// if (((daq->di_bit_prev & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_NULL) & -// ((daq->di_bit_now & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_DI_SHUTTER) & -// (daq->flag_scanner == DAQ_PORT_NULL)) -// { -// daq->flag_scanner = DAQ_PORT_TRUE; -// daq->di_cntr_imaq++; -// daq->di_cntr_frame = 0; - -// /* switch OFF box internal resonance generator */ -// DAQmxTriggerDO(DAQ_PORT_DO_FREQGEN, FALSE); -// } - -// /* SHUTTER OFF condition, SHUTTER line changes from 1 to 0 */ -// if (((daq->di_bit_prev & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_DI_SHUTTER) & -// ((daq->di_bit_now & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_NULL) & -// (daq->flag_scanner == DAQ_PORT_TRUE)) -// { -// daq->flag_scanner = DAQ_PORT_NULL; - -// /* switch ON box internal resonance generator */ -// DAQmxTriggerDO(DAQ_PORT_DO_FREQGEN, FALSE); -// } - -// /* 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++; -// DAQmxLogToFile(daq->fp_log, "FRAME", daq->di_cntr_imaq, daq->di_cntr_frame); -// } - -// /* 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++; -// DAQmxLogToFile(daq->fp_log, "LICK", DAQ_PORT_DI_LICK, daq->di_cntr_lick); - -// /* every N licks give a reward */ -// if ((daq->di_cntr_lick % 16) == 0) -// DAQmxTriggerDO(DAQ_PORT_DO_WATER, TRUE); - -// } - -// /* update bit history */ -// daq->di_bit_prev = daq->di_bit_now; -// } + DAQmxEngine *daq = (DAQmxEngine *)callbackData; + + int32 read = 0; + if (taskHandle != 0) + DAQmxErrChk(DAQmxReadDigitalU8(taskHandle, 1, 10.0, DAQmx_Val_GroupByChannel, &daq->di_bit_now, 1, &read, NULL)); + + if (read) + { + /* SHUTTER ON condition, SHUTTER line changes from 0 to 1 */ + if (((daq->di_bit_prev & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_NULL) & + ((daq->di_bit_now & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_DI_SHUTTER) & + (daq->flag_scanner == DAQ_PORT_NULL)) + { + daq->flag_scanner = DAQ_PORT_TRUE; + daq->di_cntr_imaq++; + daq->di_cntr_frame = 0; + + /* switch OFF box internal resonance generator */ + //DAQmxTriggerDO(DAQ_PORT_DO_FREQGEN, FALSE); + } + + /* SHUTTER OFF condition, SHUTTER line changes from 1 to 0 */ + if (((daq->di_bit_prev & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_DI_SHUTTER) & + ((daq->di_bit_now & DAQ_PORT_DI_SHUTTER) == DAQ_PORT_NULL) & + (daq->flag_scanner == DAQ_PORT_TRUE)) + { + daq->flag_scanner = DAQ_PORT_NULL; + + /* switch ON box internal resonance generator */ + //DAQmxTriggerDO(DAQ_PORT_DO_FREQGEN, FALSE); + } + + /* 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++; + DAQmxLogToFile(daq->fp_log, "FRAME", daq->di_cntr_imaq, daq->di_cntr_frame); + } + + /* 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++; + DAQmxLogToFile(daq->fp_log, "LICK", DAQ_PORT_DI_LICK, daq->di_cntr_lick); + + /* every N licks give a reward */ + if ((daq->di_cntr_lick % 16) == 0){ + } + //DAQmxTriggerDO(DAQ_PORT_DO_WATER, TRUE); + + } + + /* 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, void *callback_data) +int32 CVICALLBACK NIDAQmxInterface::FcnCbckTriggerStopDO(TaskHandle taskHandle, int32 signalID, void* callbackData) { -// DAQmxEngine *daq = (DAQmxEngine *)callback_data; -// int32 written = 0; - -// /* flip query bit, to switch off pulse */ -// if (daq->do_port != 0) -// { -// daq->do_bit_wrt ^= daq->do_bit_qry; -// DAQmxErrChk(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"); -// exit(EXIT_FAILURE); -// } - -// /* log trigger */ -// DAQmxLogToFile(daq->fp_log, "TRIGGER", daq->do_bit_qry, (daq->do_bit_qry & daq->do_bit_wrt) == daq->do_bit_qry); + DAQmxEngine *daq = (DAQmxEngine *)callbackData; + + int32 written = 0; + /* flip query bit, to switch off pulse */ + if (daq->do_port != 0) + { + daq->do_bit_wrt ^= daq->do_bit_qry; + DAQmxErrChk(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"); + exit(EXIT_FAILURE); + } + + /* log trigger */ + //DAQmxLogToFile(daq->fp_log, "TRIGGER", daq->do_bit_qry, (daq->do_bit_qry & daq->do_bit_wrt) == daq->do_bit_qry); return 0; } diff --git a/NIDAQmxInterface.h b/NIDAQmxInterface.h index d10a301..f0d41e9 100644 --- a/NIDAQmxInterface.h +++ b/NIDAQmxInterface.h @@ -6,37 +6,16 @@ #include #include #include -#include "C:\Program Files (x86)\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h" -//#include +#include +#include "C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\NIDAQmx.h" + + +int32 CVICALLBACK ChangeDetectionCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData); +int32 CVICALLBACK ChangeTriggerStopCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData); class NIDAQmxInterface { - /* define port bit states */ - #define DAQ_PORT_NULL 0x00 - #define DAQ_PORT_TRUE 0x01 - - #define DAQ_PORT_DI_SHUTTER 0x01 - #define DAQ_PORT_DI_BACKLIGHT 0x02 - #define DAQ_PORT_DI_FRAME 0x04 - #define DAQ_PORT_DI_AIR 0x08 - #define DAQ_PORT_DI_WATER 0x10 - #define DAQ_PORT_DI_SOUND 0x20 - #define DAQ_PORT_DI_LICK 0x40 - #define DAQ_PORT_DI_SCANNER 0x80 - - #define DAQ_PORT_DO_MONITOR 0x01 - #define DAQ_PORT_DO_AIR 0x02 - #define DAQ_PORT_DO_WATER 0x04 - #define DAQ_PORT_DO_SOUND 0x08 - #define DAQ_PORT_DO_IMGAQ 0x10 - #define DAQ_PORT_DO_FREQGEN 0x20 - - #define DAQ_PORT_DE_MONITOR 0x01 - #define DAQ_PORT_DE_AIR 0x02 - #define DAQ_PORT_DE_WATER 0x04 - - #define DO_PULSE_WIDTH 0.08// in seconds /* define DAQmxErrChk macro */ #define DAQmxErrChk(functionCall)\ @@ -68,6 +47,32 @@ class NIDAQmxInterface public: + /* define port bit states */ + static const int DAQ_PORT_NULL = 0x00; + static const int DAQ_PORT_TRUE = 0x01; + + static const int DAQ_PORT_DI_SHUTTER = 0x01; + static const int DAQ_PORT_DI_BACKLIGHT = 0x02; + static const int DAQ_PORT_DI_FRAME = 0x04; + static const int DAQ_PORT_DI_AIR = 0x08; + static const int DAQ_PORT_DI_WATER = 0x10; + static const int DAQ_PORT_DI_SOUND = 0x20; + static const int DAQ_PORT_DI_LICK = 0x40; + static const int DAQ_PORT_DI_SCANNER = 0x80; + + static const int DAQ_PORT_DO_MONITOR = 0x01; + static const int DAQ_PORT_DO_AIR = 0x02; + static const int DAQ_PORT_DO_WATER = 0x04; + static const int DAQ_PORT_DO_SOUND = 0x08; + static const int DAQ_PORT_DO_IMGAQ = 0x10; + static const int DAQ_PORT_DO_FREQGEN = 0x20; + + static const int DAQ_PORT_DE_MONITOR = 0x01; + static const int DAQ_PORT_DE_AIR = 0x02; + static const int DAQ_PORT_DE_WATER = 0x04; + + const double DO_PULSE_WIDTH = 0.08;// in seconds + explicit NIDAQmxInterface(); /* function prototypes */ void DAQmxInitializeInterface(); @@ -80,11 +85,15 @@ class NIDAQmxInterface void DAQmxWriteDO(uInt8); void DAQmxLogToFile(FILE *, const char *, uInt32, uInt32); + DAQmxEngine* daq; /*MAKE PRIVATE*/ + private: /* events callback functions */ - int32 CVICALLBACK FcnCbckDetectDI(TaskHandle, int32, void *); - int32 CVICALLBACK FcnCbckTriggerStopDO(TaskHandle, int32, void *); - DAQmxEngine* daq; + int32 CVICALLBACK FcnCbckDetectDI(TaskHandle, int32, void *callback_data); + int32 CVICALLBACK FcnCbckTriggerStopDO(TaskHandle, int32, void *callback_data); + friend int32 CVICALLBACK ChangeDetectionCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData); + friend int32 CVICALLBACK ChangeTriggerStopCallbackWrapper(TaskHandle taskHandle, int32 signalID, void *callbackData); + #endif /* define (NIDAQmxInterface_h) */ }; diff --git a/StateMachineController.cpp b/StateMachineController.cpp index ab3d3aa..05895ca 100644 --- a/StateMachineController.cpp +++ b/StateMachineController.cpp @@ -54,7 +54,7 @@ StateMachineController::StateMachineController(QObject *parent) //connect(state_iti, SIGNAL(entered()), mainTimer, SLOT(start())); // state user reaction connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered())); - /////connect(state_settings.userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer())); + //connect(state_settings.userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer())); //connect(state_settings.userReaction, SIGNAL(entered()), mainTimer, SLOT(start())); // state baseline connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered())); @@ -64,12 +64,12 @@ StateMachineController::StateMachineController(QObject *parent) connect(state_sound, SIGNAL(exited()), this, SLOT(onStateSoundExited())); connect(pausedState, SIGNAL(entered()), this, SLOT(onStatePauseEntered())); - rp = new RPCOXLib::RPcoX(); - //daq = new DAQmxEngine(); - //DAQmxSetDefaultEngine(daq); - //DAQmxInitializeInterface(daq); - //DAQmxLogToFile(daq->fp_log, "INIT", 0, 0); + nidaq = new NIDAQmxInterface(); + nidaq->DAQmxSetDefaultEngine(); + nidaq->DAQmxInitializeInterface(); + tdt = new TDTInterface(); + tdt->initializeInterface(); } void StateMachineController::startStateMachine(audioGameSettings settings) @@ -80,60 +80,9 @@ void StateMachineController::startStateMachine(audioGameSettings settings) this->settings = settings; trialsCurrent = 1; // set index for first trial (1-based) trialsTotal = settings.trialSequence.length(); - //rp->ReadTag("test"); - /* connect to RP2 system */ - if (!rp->ConnectRP2("USB", 1)) - { - fprintf(stderr, "TDTError:TDTInterface/TDTInitializeInterface:\n\tfailed to connect to RP2!\n"); - exit(EXIT_FAILURE); - } - - /* check status */ -// tdt_status = rp->GetStatus(); - - /* check if device is connected */ -// if ((tdt_status & TDT_STATUS_CONNECTED) == TDT_STATUS_CONNECTED) -// { -// printf("TDT RP2 connected\n"); - -// /* check if device is running */ -// if ((tdt_status & TDT_STATUS_CIRCUIT_RUNNING) == TDT_STATUS_CIRCUIT_RUNNING) -// rp->Halt(); - -// /* check if device memory is full */ -// if ((tdt_status & TDT_STATUS_CIRCUIT_LOADED) == TDT_STATUS_CIRCUIT_LOADED) -// rp->ClearCOF(); -// } - QString fileName; - rp->Halt(); - rp->ClearCOF(); -//RP.GetSFreq/2 - // rp->LoadCOF(settings.fileNameNegative); - - - -// /* set default values */ -// sm->state = STATE_IDLE; -// sm->duration = 0; -// sm->rcx_file = SM_RCX_POSITIVE; -// sm->snd_bit = 0x00; -// sm->trigger_count = 0; - -// /* interface SDL */ -// //SDLInitialize(); - -// /* interface TDT */ -// TDTInitializeInterface(); - -// /* allocate DAQ */ -// daq = (DAQmxEngine *)malloc(sizeof(DAQmxEngine)); -// DAQmxInitializeInterface(daq); -// DAQmxLogToFile(daq->fp_log, "INIT", 0, 0); // start state machine stateMachine->start(); -// /qDebug() << settings.itiSequence - } void StateMachineController::pauseStateMachine() @@ -185,15 +134,14 @@ void StateMachineController::onStateUserReactionEntered() void StateMachineController::onStateAcquisitionBaselineEntered() { qDebug()<< "Starting baseline"; - emit(statusMessage("Starting baseline")); - mainTimer->setInterval(settings.preImaq * 1000); mainTimer->start(); } void StateMachineController::onStateSoundEntered() { + qDebug()<< "Loading sound"; int soundType = settings.trialSequence.first(); settings.trialSequence.pop_front(); @@ -201,25 +149,18 @@ void StateMachineController::onStateSoundEntered() switch(soundType){ case 0: mainTimer->setInterval(settings.soundDurationNegative * 1000); - //state_sound->assignProperty(mainTimer, "interval", (settings.soundDurationNegative * 1000)); qDebug() << "Loading negative sound file:" << settings.fileNameNegative; - rp->LoadCOF(settings.fileNameNegative); - rp->Run(); - //TDTLoadRCXCircuit(settings.fileNameNegative); + tdt->loadRCXCircuit(settings.fileNameNegative); break; case 1: mainTimer->setInterval(settings.soundDurationPositive * 1000); - //state_sound->assignProperty(mainTimer, "interval", (settings.soundDurationPositive * 1000)); qDebug() << "Loading positive sound file:" << settings.fileNamePositive; - //TDTLoadRCXCircuit(settings.fileNamePositive); - rp->LoadCOF(settings.fileNamePositive); - rp->Run(); + tdt->loadRCXCircuit(settings.fileNamePositive); break; } mainTimer->start(); - //DAQmxTriggerDO(daq, DAQ_PORT_DO_SOUND, true); - + nidaq->DAQmxTriggerDO(NIDAQmxInterface::DAQ_PORT_DO_SOUND, true); qDebug()<< "Starting sound"; emit(statusMessage("Starting sound")); @@ -238,9 +179,10 @@ void StateMachineController::onStateSoundExited() } else { mainTimer->stop(); stateMachine->stop(); + timerDialog->removeTimer(); qDebug() << "Terminated"; - //ui->statusBar->showMessage("Terminated"); - //ui->pushButton_Run->setText("Run"); + emit(statusMessage("Terminated")); + emit(terminated()); } } diff --git a/StateMachineController.h b/StateMachineController.h index 9ed0bac..28e908c 100644 --- a/StateMachineController.h +++ b/StateMachineController.h @@ -16,9 +16,7 @@ #include "SettingStructures.h" #include "TimerDialog.h" #include "NIDAQmxInterface.h" - -//#include "TDTInterface.h" -#include "rpcoxlib.h" +#include "TDTInterface.h" class StateMachineController : public QObject { @@ -44,8 +42,8 @@ class StateMachineController : public QObject QTimer *mainTimer; TimerDialog *timerDialog; - //DAQmxEngine* daq; - RPCOXLib::RPcoX* rp; + NIDAQmxInterface* nidaq; + TDTInterface* tdt; int trialsTotal = -1; int trialsCurrent = -1; // is gonna be 1-based, so first trial has index 1 @@ -61,9 +59,9 @@ public slots: signals: void statusMessage(QString); + void terminated(); void pauseRequested(); - }; #endif // STATEMACHINECONTROLLER_H diff --git a/TDTInterface.cpp b/TDTInterface.cpp index e847464..22d948d 100644 --- a/TDTInterface.cpp +++ b/TDTInterface.cpp @@ -1,48 +1,18 @@ #include "TDTInterface.h" -/* global variables */ -RPCOXLib::RPcoX* rp; -HRESULT hr; -long int tdt_status; - /* initialize TDT Sound System */ -void TDTInitializeInterface(void) +void TDTInterface::initializeInterface() { - rp = new RPCOXLib::RPcoX(); - -// /* initialize ActiveX handle */ -// hr = CoInitialize(NULL); -// if (FAILED(hr)) -// { -// fprintf(stderr, "TDTError:TDTInterface/TDTInitializeInterface:\n\tfailed to initialize COM handle!\n"); -// exit(EXIT_FAILURE); -// } - -// /* initialize ActiveX object instance */ -// hr = rp.CreateInstance(TDT_APP_ID); -// if (FAILED(hr)) -// { -// fprintf(stderr, "TDTError:TDTInterface/TDTInitializeInterface:\n\t ActiveX COM instance for %s failed!\n", TDT_APP_ID); -// exit(EXIT_FAILURE); -// } -// //printf("TDT ActiveX instance is initialized\napp_id: %s\n", TDT_APP_ID); - -// /* check if ActiveX object pointer is set */ -// if (rp == 0) -// { -// fprintf(stderr, "TDTError:TDTInterface/TDTInitializeInterface:\n\t ActiveX COM object pointer is not set!\n"); -// exit(EXIT_FAILURE); -// } /* connect to RP2 system */ - if (!rp->ConnectRP2("USB", 1)) + if (!rp.ConnectRP2("USB", 1)) { fprintf(stderr, "TDTError:TDTInterface/TDTInitializeInterface:\n\tfailed to connect to RP2!\n"); exit(EXIT_FAILURE); } /* check status */ - tdt_status = rp->GetStatus(); + tdt_status = rp.GetStatus(); /* check if device is connected */ if ((tdt_status & TDT_STATUS_CONNECTED) == TDT_STATUS_CONNECTED) @@ -51,68 +21,66 @@ void TDTInitializeInterface(void) /* check if device is running */ if ((tdt_status & TDT_STATUS_CIRCUIT_RUNNING) == TDT_STATUS_CIRCUIT_RUNNING) - rp->Halt(); + rp.Halt(); /* check if device memory is full */ if ((tdt_status & TDT_STATUS_CIRCUIT_LOADED) == TDT_STATUS_CIRCUIT_LOADED) - rp->ClearCOF(); + rp.ClearCOF(); } return; } /* destroy TDT Engine */ -void TDTDestroyInterface(void) +void TDTInterface::destroyInterface() { /* check status */ - tdt_status = rp->GetStatus(); + tdt_status = rp.GetStatus(); /* check if device is connected */ if ((tdt_status & TDT_STATUS_CONNECTED) == TDT_STATUS_CONNECTED) { /* check if device is running */ if ((tdt_status & TDT_STATUS_CIRCUIT_RUNNING) == TDT_STATUS_CIRCUIT_RUNNING) - rp->Halt(); + rp.Halt(); /* check if device memory is full */ if ((tdt_status & TDT_STATUS_CIRCUIT_LOADED) == TDT_STATUS_CIRCUIT_LOADED) - rp->ClearCOF(); + rp.ClearCOF(); } - rp->clear(); - delete rp; - + rp.clear(); return; } -void TDTLoadRCXCircuit(const char *rcx_file) +void TDTInterface::loadRCXCircuit(QString fileName) { /* check status */ - tdt_status = rp->GetStatus(); + tdt_status = rp.GetStatus(); /* check if device is connected */ if ((tdt_status & TDT_STATUS_CONNECTED) == TDT_STATUS_CONNECTED) { /* check if device is running */ if ((tdt_status & TDT_STATUS_CIRCUIT_RUNNING) == TDT_STATUS_CIRCUIT_RUNNING) - rp->Halt(); + rp.Halt(); /* check if device memory is full */ if ((tdt_status & TDT_STATUS_CIRCUIT_LOADED) == TDT_STATUS_CIRCUIT_LOADED) - rp->ClearCOF(); + rp.ClearCOF(); /* load circuit */ - rp->LoadCOF(rcx_file); + rp.LoadCOF(fileName); /* update status */ - tdt_status = rp->GetStatus(); + tdt_status = rp.GetStatus(); if ((tdt_status & TDT_STATUS_CIRCUIT_LOADED) == TDT_STATUS_NULL) { - fprintf(stderr, "TDTError:TDTInterface/TDTLoadRCXCircuit:\n\tfailed to load %s\n%s\n", rcx_file); + fprintf(stderr, "TDTError:TDTInterface/TDTLoadRCXCircuit:\n\tfailed to load %s\n%s\n", fileName); exit(EXIT_FAILURE); } /* run circuit */ - rp->Run(); + rp.Run(); } return; } diff --git a/TDTInterface.h b/TDTInterface.h index 321aa5e..4fb1efc 100644 --- a/TDTInterface.h +++ b/TDTInterface.h @@ -5,14 +5,25 @@ #include #include "rpcoxlib.h" -#define TDT_STATUS_NULL 0x00 -#define TDT_STATUS_CONNECTED 0x01 -#define TDT_STATUS_CIRCUIT_LOADED 0x02 -#define TDT_STATUS_CIRCUIT_RUNNING 0x04 +class TDTInterface +{ +public: + static const int TDT_STATUS_NULL = 0x00; + static const int TDT_STATUS_CONNECTED = 0x01; + static const int TDT_STATUS_CIRCUIT_LOADED = 0x02; + static const int TDT_STATUS_CIRCUIT_RUNNING = 0x04; -///* funciton prototypes */ -void TDTInitializeInterface(void); -void TDTLoadRCXCircuit(const char *); -void TDTDestroyInterface(void); + ///* funciton prototypes */ + void initializeInterface(); + void loadRCXCircuit(QString fileName); + void destroyInterface(); + + /* global variables */ + //RPCOXLib::RPcoX* rp; + RPCOXLib::RPcoX rp; + HRESULT hr; + long int tdt_status; + +}; #endif /* define (TDTInterface_h) */ diff --git a/mainwindow.ui b/mainwindow.ui index 96c6a96..6993f49 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -158,7 +158,7 @@ 0 - + @@ -337,7 +337,7 @@ 10 - + @@ -415,7 +415,7 @@ 0 0 472 - 27 + 21 @@ -441,11 +441,11 @@ pushButton_selectOutputFolder lineEdit_outputFilename checkBox_autoFilename - lineEdit_selectFilePositive + lineEdit_filePositive pushButton_selectFilePositive lineEdit_soundDurationPositive lineEdit_repeatPositive - lineEdit_selectFileNegative + lineEdit_fileNegative pushButton_selectFileNegative lineEdit_soundDurationNegative lineEdit_repeatNegative diff --git a/timerdialog.ui b/timerdialog.ui index 08fde3c..9043c20 100644 --- a/timerdialog.ui +++ b/timerdialog.ui @@ -6,49 +6,39 @@ 0 0 - 400 - 238 + 454 + 111 Dialog - - - - 120 - 100 - 211 - 91 - - - - - 34 - - - - time - - - - - - 40 - 50 - 351 - 61 - - - - - 20 - - - - Time until microscope acquires data: - - + + + + + + 20 + + + + Time until microscope acquires data: + + + + + + + + 34 + + + + time + + + +