This repository has been archived by the owner. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved statemachine to separate class
1 parent
22ca327
commit 305f526
Showing
4 changed files
with
288 additions
and
341 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include "StateMachineController.h" | ||
|
||
StateMachineController::StateMachineController(QWidget *parent) | ||
{ | ||
// seed randomizer | ||
srand(time(0)); | ||
// //timerDialog = new TimerDialog(); | ||
|
||
mainTimer = new QTimer(this); | ||
mainTimer->setSingleShot(true); | ||
|
||
// Create and start the state machine | ||
setupStateMachine(); | ||
|
||
} | ||
|
||
void StateMachineController::setupStateMachine() | ||
{ | ||
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); | ||
|
||
/** | ||
* Depending on whether we are in runningState or pausedState, the 'paused' property | ||
* of the object will be set to false/true. | ||
*/ | ||
|
||
runningState->assignProperty(this, "paused", false); | ||
pausedState->assignProperty(this, "paused", true); | ||
|
||
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())); | ||
//connect(state_preDelay, SIGNAL(entered()), mainTimer, SLOT(start())); // start timer on state entered | ||
// state ITI | ||
connect(state_iti, SIGNAL(entered()), this, SLOT(onStateItiEntered())); | ||
//connect(state_iti, SIGNAL(entered()), mainTimer, SLOT(start())); | ||
// state user reaction | ||
connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered())); | ||
/////connect(state_userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer())); | ||
//connect(state_userReaction, SIGNAL(entered()), mainTimer, SLOT(start())); | ||
// state baseline | ||
connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered())); | ||
//connect(state_acquisitionBaseline, SIGNAL(entered()), mainTimer, SLOT(start())); | ||
// state sound | ||
connect(state_sound, SIGNAL(entered()), this, SLOT(onStateSoundEntered())); | ||
//connect(state_sound, SIGNAL(entered()), mainTimer, SLOT(start())); | ||
connect(state_sound, SIGNAL(exited()), this, SLOT(onStateSoundExited())); | ||
|
||
} | ||
|
||
void StateMachineController::runStateMachine() | ||
{ | ||
trialsCurrent = 1; // set index for first trial (1-based) | ||
trialsTotal = trialSequence.length(); | ||
|
||
// start state machine | ||
stateMachine->start(); | ||
} | ||
|
||
|
||
void StateMachineController::onStatePreDelayEntered() | ||
{ | ||
qDebug() << "Pre delay"; | ||
emit(statusMessage("Pre delay running")); | ||
|
||
mainTimer->setInterval(preDelay * 1000); | ||
mainTimer->start(); | ||
} | ||
|
||
void StateMachineController::onStateItiEntered() | ||
{ | ||
qDebug() << "Entered Iti"; | ||
emit(statusMessage("Starting trial begin")); | ||
|
||
double nextItiValue = 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(userReaction); | ||
// timerDialog->show(); | ||
// timerDialog->startTimer(); | ||
|
||
qDebug()<< "Starting user reaction"; | ||
emit(statusMessage("Starting user reaction")); | ||
|
||
mainTimer->setInterval(userReaction * 1000); | ||
mainTimer->start(); | ||
} | ||
|
||
void StateMachineController::onStateAcquisitionBaselineEntered() | ||
{ | ||
qDebug()<< "Starting baseline"; | ||
|
||
emit(statusMessage("Starting baseline")); | ||
|
||
mainTimer->setInterval(preImaq * 1000); | ||
mainTimer->start(); | ||
} | ||
|
||
void StateMachineController::onStateSoundEntered() | ||
{ | ||
|
||
int soundType = trialSequence.first(); | ||
trialSequence.pop_front(); | ||
|
||
if (soundType == 1) { | ||
mainTimer->setInterval(soundDurationPositive * 1000); | ||
//state_sound->assignProperty(mainTimer, "interval", (soundDurationPositive * 1000)); | ||
} else if (soundType == 0) { | ||
mainTimer->setInterval(soundDurationNegative * 1000); | ||
//state_sound->assignProperty(mainTimer, "interval", (soundDurationNegative * 1000)); | ||
} | ||
mainTimer->start(); | ||
|
||
qDebug()<< "Starting sound"; | ||
emit(statusMessage("Starting sound")); | ||
|
||
} | ||
|
||
void StateMachineController::onStateSoundExited() | ||
{ | ||
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(); | ||
qDebug() << "Terminated"; | ||
//ui->statusBar->showMessage("Terminated"); | ||
//ui->pushButton_Run->setText("Run"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#ifndef STATEMACHINECONTROLLER_H | ||
#define STATEMACHINECONTROLLER_H | ||
#include <QObject> | ||
#include <QTimer> | ||
#include <QElapsedTimer> | ||
#include <QVector> | ||
#include <QStateMachine> | ||
#include <QState> | ||
#include <QHistoryState> | ||
#include <QDebug> | ||
|
||
#include <ctime> | ||
#include <algorithm> //std::random_shuffle | ||
|
||
class StateMachineController : public QObject | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit StateMachineController(QWidget *parent = 0); | ||
|
||
double preDelay = -1; | ||
double iti = -1; | ||
double userReaction = 30; //sec | ||
double preImaq = -1; | ||
double soundDurationPositive = -1; | ||
double soundDurationNegative = -1; | ||
|
||
QVector<int> trialSequence; | ||
QVector<double> itiSequence; | ||
|
||
void setupStateMachine(); | ||
void runStateMachine(); | ||
|
||
private: | ||
// state machine | ||
QStateMachine *stateMachine; | ||
QState *state_preDelay; | ||
QState *state_iti; | ||
QState *state_userReaction; | ||
QState *state_acquisitionBaseline; | ||
QState *state_sound; | ||
|
||
bool m_paused; | ||
|
||
// the timer that triggers the state changes | ||
QTimer *mainTimer; | ||
|
||
int trialsTotal = -1; | ||
int trialsCurrent = -1; // is gonna be 1-based, so first trial has index 1 | ||
|
||
|
||
public slots: | ||
void onStatePreDelayEntered(); | ||
void onStateItiEntered(); | ||
void onStateUserReactionEntered(); | ||
void onStateAcquisitionBaselineEntered(); | ||
void onStateSoundEntered(); | ||
void onStateSoundExited(); | ||
|
||
|
||
|
||
|
||
signals: | ||
void statusMessage(QString); | ||
|
||
Q_SIGNALS: | ||
// change notification signals for the state properties | ||
void pausedChanged(); | ||
/** | ||
* This signal is emitted when the pause() slot is invoked and is used | ||
* by the internal state machine only. | ||
*/ | ||
void pauseRequested(); | ||
|
||
|
||
}; | ||
|
||
#endif // STATEMACHINECONTROLLER_H |
Oops, something went wrong.