using System; using System.Threading; using Microsoft.SPOT; namespace MFConsoleApplication1 { public class Program { public enum MissionPhase : int { Initialize = 0, PreDeployment, PreMissionDelay, GotoBottom, DwellOnBottom, GotoSurface, Surface, Exit, } public struct MissionState { public static bool runMission; public static MissionPhase missionPhase; public static int profileNum; public static int errorCode; } public struct ConfigFile //Eventually this will all be read from a file { public static String DGHPressurePortName = "COM3"; public static String ElmoPortName = "COM2"; public static String ConsolePortName = "COM1"; public static double[] depthTable = { 5.0, 0.0 }; //in dBar public static int preMissionDelayMinutes = 1; public static int dwellAtDepthMinutes = 3; public static int descendTimeoutMinutes = 10; public static int ascendTimeoutMinutes = 10; } public static AutoResetEvent wakeStateMachineEvent = new AutoResetEvent(false); public static String DateTimeNowMilliSec() { DateTime timeNow = DateTime.Now; String temp = timeNow.ToString() + "." + timeNow.Millisecond.ToString(); return (temp); } public static void Main() { Debug.Print("\r\nStarting Program ...\r\n"); String consoleCmd; MissionState.missionPhase = MissionPhase.Initialize; MissionState.runMission = true; MissionState.profileNum = 0; while (MissionState.runMission) { switch (MissionState.missionPhase) { case (MissionPhase.Initialize): /* CPF sitting on deck * Just powered up * Run whatever initialize stuff needs to be done */ EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Initialize Phase"); DGHPressure.init(ConfigFile.DGHPressurePortName); Elmo.initElmo(ConfigFile.ElmoPortName); Console.initConsole(ConfigFile.ConsolePortName); MissionState.missionPhase = MissionPhase.PreDeployment; break; case (MissionPhase.PreDeployment): /* CPF still sitting on deck * Run pre-deployment check out * telemeter the results up */ EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting PreDeployment Phase"); //Eventually wait for command to transition state to Pre-mission delay phase MissionState.missionPhase = MissionPhase.PreMissionDelay; break; case (MissionPhase.PreMissionDelay): /* Heave the CPF over the side * wait for a command to start the mission * or exit the mission */ EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting PreMissionDelay Phase"); consoleCmd = Console.readCommand(); switch (consoleCmd) { case (Console.BeginCmd): MissionState.missionPhase = MissionPhase.GotoBottom; Thread.Sleep(ConfigFile.preMissionDelayMinutes); //This probably won't be in real mission, it just gives me time to get the CPF off the crane hook break; case (Console.ExitCmd): MissionState.missionPhase = MissionPhase.Exit; break; default: Console.InvalidCommandReceived("Only BG and EX commands are valid at this point\r\n"); break; } break; case (MissionPhase.GotoBottom): EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Descend Phase"); MissionState.errorCode = BuoyancyControl.GotoDepth(ConfigFile.depthTable[MissionState.profileNum]); if (wakeStateMachineEvent.WaitOne(600000, false)) /* waiting for notification, 10 minute timeout, eventually timeout * should be calculated based on profile rate and desired depth */ { EngrLog.writeEvent(Program.DateTimeNowMilliSec() + " ,Returned from GotoBottom GotoDepth"); MissionState.missionPhase = MissionPhase.DwellOnBottom; } else { EngrLog.writeEvent(Program.DateTimeNowMilliSec() + " ,Timed out waiting for GotoBottom GotoDepth"); //Eventually deal with error(s) } break; case (MissionPhase.DwellOnBottom): //Hold depth EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Dwell At Depth Phase"); Thread.Sleep(ConfigFile.dwellAtDepthMinutes); /*eventually this needs to do a lot more like check to make * sure we're staying on the bottom and adjust buoyancy as * necessary */ MissionState.missionPhase = MissionPhase.GotoSurface; break; case (MissionPhase.GotoSurface): EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Ascend Phase"); MissionState.errorCode = BuoyancyControl.GotoDepth(0); if (wakeStateMachineEvent.WaitOne(600000, false)) /*waiting for notification, 10 minute timeout, eventually timeout * should be calculated based on profile rate and desired depth */ { EngrLog.writeEvent(Program.DateTimeNowMilliSec() + " ,Returned from GotoBottom GotoDepth"); MissionState.missionPhase = MissionPhase.Surface; } else { EngrLog.writeEvent(Program.DateTimeNowMilliSec() + " ,Timed out waiting for GotoBottom GotoDepth"); //Eventually deal with error(s) } break; case (MissionPhase.Surface): // eventually this is where the Iridium/Wifi will happen EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Surface Interval Phase"); consoleCmd = Console.readCommand(); switch (consoleCmd) { case (Console.BeginCmd): MissionState.missionPhase = MissionPhase.GotoBottom; Thread.Sleep(ConfigFile.preMissionDelayMinutes); //This probably won't be in real mission, it just gives me time to get the CPF off the crane hook break; case (Console.UploadCmd): /* If data exists, send it otherwise * Send "Pre Deployment Phase No Data Yet message" * Wait for next command */ EngrLog.uploadData(); MissionState.missionPhase = MissionPhase.Surface; break; case (Console.ExitCmd): MissionState.missionPhase = MissionPhase.Exit; break; default: Console.InvalidCommandReceived("Only BG, UP and EX commands are valid at this point\r\n"); break; } break; case (MissionPhase.Exit): //Exit the program EngrLog.writeEvent(DateTimeNowMilliSec() + " ,Starting Exit Phase"); break; } //end switch } //end run mission } //end main } //end Class program } //end Namespace