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 "StateMachineController.h"
StateMachineController::StateMachineController(QObject *parent):
QObject(parent)
{
qRegisterMetaType<QVector<double>>("QVector<double>");
// seed randomizer
srand(time(0));
timerDialog = new TimerDialog();
mainTimer = new QTimer(this);
mainTimer->setSingleShot(true);
stateMachine = new QStateMachine(this);
// Create the two top-level states
QState *runningState = new QState(stateMachine);
QState *pausedState = new QState(stateMachine);
// set up state machine
QState *state_preDelay = new QState(runningState);
QState *state_iti = new QState(runningState);
QState *state_userReaction = new QState(runningState);
QState *state_acquisitionBaseline = new QState(runningState);
QState *state_sound = new QState(runningState);
QHistoryState *historyState = new QHistoryState(runningState);
state_preDelay->addTransition(mainTimer, SIGNAL(timeout()), state_iti);
state_iti->addTransition(mainTimer, SIGNAL(timeout()), state_userReaction);
state_userReaction->addTransition(mainTimer, SIGNAL(timeout()), state_acquisitionBaseline);
state_acquisitionBaseline->addTransition(mainTimer, SIGNAL(timeout()), state_sound);
state_sound->addTransition(mainTimer, SIGNAL(timeout()), state_iti);
/**
* If we are in runningState and the pauseRequested() signal is emitted (that happens
* when the pause() slot has been invoked) then we go to the pausedState.
* If we are now in the pausedState and the pauseRequested() signal is emitted again,
* we go to the historyState which will forward us to the phase state we have been in
* when we left the runningState.
*/
runningState->addTransition(this, SIGNAL(pauseRequested()), pausedState);
pausedState->addTransition(this, SIGNAL(pauseRequested()), historyState);
// Define which child state should be the initial state
runningState->setInitialState(state_preDelay);
stateMachine->setInitialState(runningState);
// connect states to functions for starting timers
// state pre delay
connect(state_preDelay, SIGNAL(entered()), this, SLOT(onStatePreDelayEntered()));
// state ITI
connect(state_iti, SIGNAL(entered()), this, SLOT(onStateItiEntered()));
// state user reaction
connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered()));
connect(state_userReaction, SIGNAL(exited()), this, SLOT(onStateUserReactionExited()));
connect(state_userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer()));
// state baseline
connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered()));
// state sound
connect(state_sound, SIGNAL(entered()), this, SLOT(onStateSoundEntered()));
/*Connect pause signals*/
connect(pausedState, SIGNAL(entered()), this, SLOT(onStatePauseEntered()));
connect(pausedState, SIGNAL(exited()), this, SLOT(onStatePauseExited()));
nidaq = new NIDAQmxInterface();
nidaq->DAQmxSetDefaultEngine();
// nidaq->DAQmxInitializeInterface();
tdt = new TDTInterface();
if(!tdt->initializeInterface()){
logFileThread = new QThread(this);
logFileWriter = new LogFileWriter();
socketThread = new QThread(this);
socketClient = new SocketClient();
/*Thread-safe event communication*/
/*Main -> Logfile*/
connect(this, SIGNAL(openLogFile(QString)), logFileWriter, SLOT(onOpen(QString)));
connect(this, SIGNAL(closeLogFile()), logFileWriter, SLOT(onClose()));
connect(this, SIGNAL(writeToLogFile(QString, uint, uint, QString)), logFileWriter, SLOT(onWrite(QString, uint, uint, QString)));
connect(nidaq, SIGNAL(writeToLogFile(QString, uint, uint, QString)), logFileWriter, SLOT(onWrite(QString, uint, uint, QString)));
/*Socket -> Logfile*/
connect(socketClient, SIGNAL(socketTrackingResult(QVector<double>)), logFileWriter, SLOT(onWriteTrackingResult(QVector<double>)));
socketClient->moveToThread(socketThread);
socketThread->start();
logFileWriter->moveToThread(logFileThread);
logFileThread->start();
}else{
QMessageBox messageBox;
messageBox.critical(0,"Error","Unable to initialize TDT audio interface!\nYou will not be able to use this device.");
}
}
StateMachineController::~StateMachineController()
{
if(logFileThread){
logFileThread->quit();
logFileThread->wait();
delete logFileWriter;
}
if(socketThread){
socketThread->quit();
socketThread->wait();
delete socketClient;
}
delete timerDialog;
delete nidaq;
delete tdt;
}
void StateMachineController::startStateMachine(audioGameSettings settings)
{
if(stateMachine->isRunning()) //this should not happen
stopStateMachine();
//stateMachine->stop();
nidaq->DAQmxInitializeInterface();
this->settings = settings;
trialsCurrent = 1; // set index for first trial (1-based)
trialsTotal = settings.trialSequence.length();
nidaq->licksToReward = settings.licksToReward;
emit(openLogFile(settings.logFileName));
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("INIT",0,0,timeString));
// start state machine
stateMachine->start();
}
void StateMachineController::pauseStateMachine()
{
emit(pauseRequested());
}
void StateMachineController::stopStateMachine()
{
qDebug()<<"StateMachineController:stopStateMachine()";
timerDialog->removeTimer();
mainTimer->stop();
stateMachine->stop();
nidaq->DAQmxDestroyInterface();
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("EXIT",0,0,timeString));
emit(closeLogFile());
}
void StateMachineController::onStatePreDelayEntered()
{
qDebug() << "Pre delay";
emit(statusMessage("Pre delay running"));
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("IDLE", 0, trialsCurrent,timeString));
mainTimer->setInterval(settings.preDelay * 1000);
mainTimer->start();
}
void StateMachineController::onStateItiEntered()
{
qDebug() << "Entered Iti";
emit(statusMessage("Starting trial begin"));
double nextItiValue = settings.itiSequence.at(trialsCurrent - 1); // -1 because trialsCurrent is 1-based
mainTimer->setInterval(nextItiValue * 1000);
mainTimer->start();
}
void StateMachineController::onStateUserReactionEntered()
{
timerDialog->removeTimer(); // remove previous timer dialog
timerDialog->setUpTimer(settings.userReaction);
timerDialog->show();
timerDialog->startTimer();
qDebug() << "Starting user reaction";
emit(statusMessage("Starting user reaction"));
mainTimer->setInterval(settings.userReaction * 1000);
mainTimer->start();
}
void StateMachineController::onStateUserReactionExited()
{
qDebug() << "Triggering microscope";
nidaq->DAQmxTriggerDO(NIDAQmxInterface::DAQ_PORT_DO_IMGAQ, true);
}
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();
switch(soundType){
case 0:
mainTimer->setInterval(settings.soundDurationNegative * 1000);
qDebug() << "Loading negative sound file:" << settings.fileNameNegative;
tdt->loadRCXCircuit(settings.fileNameNegative);
break;
case 1:
mainTimer->setInterval(settings.soundDurationPositive * 1000);
qDebug() << "Loading positive sound file:" << settings.fileNamePositive;
tdt->loadRCXCircuit(settings.fileNamePositive);
break;
}
qDebug() << "Starting sound";
emit(statusMessage("Starting sound"));
mainTimer->start();
nidaq->DAQmxTriggerDO(NIDAQmxInterface::DAQ_PORT_DO_SOUND, true);
qDebug() << "Finished sound";
emit(statusMessage("Finished sound"));
// go to next trial
if(trialsCurrent < trialsTotal) {
//increase trial index
trialsCurrent++;
// or terminate
} else {
mainTimer->stop();
stateMachine->stop();
nidaq->DAQmxDestroyInterface();
qDebug() << "Terminated";
emit(statusMessage("Terminated"));
emit(terminated());
QString timeString = QTime::currentTime().toString("hh:mm:ss.zzz");
emit(writeToLogFile("EXIT",0,0,timeString));
emit(closeLogFile());
}
}
void StateMachineController::onStatePauseEntered()
{
qDebug() << "Pause state entered";
mainTimer->stop();
nidaq->isPaused = true;
timerDialog->removeTimer();
}
void StateMachineController::onStatePauseExited()
{
nidaq->isPaused = false;
qDebug() << "Pause state exited";
}