/// <summary> /// Gets the one and only instance of this class that is allowed to exist. /// </summary> /// <returns>Instance of Microcontroller class</returns> public static Microcontroller GetInstance() { if (_instance == null) { lock (_instance_lock) { if (_instance == null) { _instance = new Microcontroller(); } } } return(_instance); }
private void _background_thread_DoWork(object sender, DoWorkEventArgs e) { //If a stage has not been defined, return immediately. We cannot proceed. if (CurrentStage == null) { return; } //Get an instance of the microcontroller that is connected to this computer var microcontroller = Microcontroller.GetInstance(); microcontroller.ConnectToMicrocontroller(); //Initialize variables for this behavior session LeftFeedCount = 0; RightFeedCount = 0; TrialState = MMazeTrialState.NoTrialStarted; IsSoundPlaying = false; //Open a file for this session _session_file_writer = new MMazeFileWriter(); _session_file_writer.CreateFile(RatName); _session_file_writer.WriteFileHeader( RatName, DateTime.Now.ToFileTime(), CurrentStage.StageName, MMazeConfiguration.GetInstance().BoothName ); //Make hard copies of the timer lists for the current stage so we can use them this session _this_session_timer_map = CurrentStage.StageRefractoryPeriods.ToList(); _this_session_max_timer_map = CurrentStage.StageMaxSoundDelays.ToList(); //Start a timer for the session. timer.Restart(); //Start timer 1 - the refractory period timer StartTimer1(); //Set the initial value of the "most recent feed" to be the current time _most_recent_feed = DateTime.Now; //Initialize the "feed lists" FeedList_TimeSincePreviousFeed = new List <int>(); FeedList_TimeSinceSessionStart = new List <int>(); lock (sound_list_lock) { SoundList_TimeSinceSessionStart = new List <int>(); } //Loop until the session is ended while (!_background_thread.CancellationPending) { //Get the total seconds elapsed so far during this session SecondsElapsed = Convert.ToInt32(timer.Elapsed.TotalSeconds); //Read in the most recent event from the microcontroller var latest_event = microcontroller.ReadStream(); if (latest_event != null && latest_event.EventType != MMazeEventNames.Undefined) { //Write the latest event to the file _session_file_writer.WriteEvent(latest_event); //If it was a feeder event, update the feed lists we are maintaining (which will also be used to update //the plot) if (latest_event.EventType == MMazeEventNames.LeftFeederTriggered || latest_event.EventType == MMazeEventNames.RightFeederTriggered) { var time_since_last_feed = DateTime.Now - _most_recent_feed; _most_recent_feed = DateTime.Now; switch (latest_event.EventType) { case MMazeEventNames.LeftFeederTriggered: LeftFeedCount++; break; case MMazeEventNames.RightFeederTriggered: RightFeedCount++; break; } FeedList_TimeSincePreviousFeed.Add(Convert.ToInt32(time_since_last_feed.TotalSeconds)); FeedList_TimeSinceSessionStart.Add(Convert.ToInt32(timer.Elapsed.TotalSeconds)); _background_properties_to_update.Add("FeedList"); } //Set the user-facing nosepoke and prox-sensor state variables based upon the most recent event //that we have received from the microcontroller switch (latest_event.EventType) { case MMazeEventNames.LeftNosepokeEnter: LeftNosepokeState = true; break; case MMazeEventNames.LeftNosepokeLeave: LeftNosepokeState = false; break; case MMazeEventNames.RightNosepokeEnter: RightNosepokeState = true; break; case MMazeEventNames.RightNosepokeLeave: RightNosepokeState = false; break; case MMazeEventNames.LeftProxEnter: LeftProxState = true; break; case MMazeEventNames.LeftProxLeave: LeftProxState = false; break; case MMazeEventNames.RightProxEnter: RightProxState = true; break; case MMazeEventNames.RightProxLeave: RightProxState = false; break; } //Handle the trial state based upon the most recent event we received from the microcontroller switch (TrialState) { case MMazeTrialState.NoTrialStarted: //Set the trial state based upon the nosepoke that has been exited if (latest_event.EventType == MMazeEventNames.LeftNosepokeLeave) { TrialState = MMazeTrialState.LeftToRight; } else if (latest_event.EventType == MMazeEventNames.RightNosepokeLeave) { TrialState = MMazeTrialState.RightToLeft; } break; case MMazeTrialState.LeftToRight: //This is a "left to right" trial, handle a beam break in the left prox area if (latest_event.EventType == MMazeEventNames.LeftProxEnter) { TrialState = MMazeTrialState.LeftToRight_EnterLeftProx; if (CurrentStage.StageCueType == MMazeStageCueType.ProximitySensor) { HandleBeamBreak(); } } break; case MMazeTrialState.RightToLeft: //This is a "right to left" trial, handle a beam break in the right prox area if (latest_event.EventType == MMazeEventNames.RightProxEnter) { TrialState = MMazeTrialState.RightToLeft_EnterRightProx; if (CurrentStage.StageCueType == MMazeStageCueType.ProximitySensor) { HandleBeamBreak(); } } break; case MMazeTrialState.LeftToRight_EnterLeftProx: //This is the end of a "left to right" trial, reset the trial state if (latest_event.EventType == MMazeEventNames.RightNosepokeEnter) { TrialState = MMazeTrialState.NoTrialStarted; if (CurrentStage.StageCueType == MMazeStageCueType.Nosepoke) { HandleBeamBreak(); } } break; case MMazeTrialState.RightToLeft_EnterRightProx: //This is the end of a "right to left" trial, reset the trial state if (latest_event.EventType == MMazeEventNames.LeftNosepokeEnter) { TrialState = MMazeTrialState.NoTrialStarted; if (CurrentStage.StageCueType == MMazeStageCueType.Nosepoke) { HandleBeamBreak(); } } break; } } //Update the GUI based on what is happening in the background thread _background_properties_to_update.Add("SoundList"); _background_thread.ReportProgress(0); //Sleep the thread Thread.Sleep(33); } //Close the file for this session _session_file_writer.WriteFileFooter(DateTime.Now.ToFileTime()); _session_file_writer.CloseFile(); //Stop the session timer timer.Stop(); //Stop the sound timers if (_timer1 != null) { _timer1.Stop(); _timer1.Close(); } if (_timer2 != null) { _timer2.Stop(); _timer2.Close(); } //Close up SecondsElapsed = 0; _background_thread.ReportProgress(0); //Report the thread being canceled e.Cancel = true; }