//#define OVERRIDE_PRESSURE //#define NO_CTD //#define DEBUG_ANNOUNCE //#define FAKE_CN0254_VOLTS //#define DEBUG_NO_STATE_TIMEOUT //#define SIM_PROFILE //#define ADD_RANDP using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using Microsoft.SPOT.IO; using System.Threading; using System.Text; using System.IO; using System.IO.Ports; using GHI.Processor; namespace abstractState { public class Program { public enum CPFStates : int { initMission = 1, initProfile, descend, ascend, surfaceOpsSetBellows, surfaceOps, preMissionDelay, dumpCPData, ABRetractFast, ABRetractSlow, park, anchor, deAnchor, startCPMode, recoveryMode, exit, cpfStatesLength } public static StateBase[] cpfState = new StateBase[(int)CPFStates.cpfStatesLength]; //TODO Think about moving to SV class. //would need to impliment interface Program-SV interface to allow setting with this current protection level //OR //just make public setable... public static CPFStates CurrentState { get; protected set; } public static CPFStates PastState { get; protected set; } public static CPFStates NextState { get; protected set; } public static bool missionRun { get; set; } public static bool timedoutTrue = true; public static bool timedoutFalse = false; public static I2CDevice g400I2C = new I2CDevice(null); private static Object programLock = new Object(); //The only timer that fires something directly is the SBE41CommandModeTimer //These timers just put a message on the queue private static Timer PTHTimer; private static Timer ADCTimer; private static int loopCounter = 0; private static double parsedPressure = double.NaN; private static TimeSpan SMCycleStartTime; private static TimeSpan SMCyclePeriod; private static StringBuilder sbTemp = new StringBuilder(128); public static StringBuilder missionFileName = new StringBuilder("mission60mWithHoldAt6.mis"); public static StructQueue sQueue = new StructQueue(); private static StructQueue.qStruct qStructure = new StructQueue.qStruct(); public static BTConsole btConsole; private static Register resetControllerStatus = new Register(0xFFFFFE04); #if(GC_INFO) private static uint freeMem = 0; private static int[] deltaMem = {0,0}; #endif public static void Main() { Debug.Print("Program Started"); missionRun = true; //TODO Add try catch block around initialization stuff //TODO implement Watchdog! GHI.Processor.Watchdog.Disable(); //GHI.Processor.Watchdog.Enable(configFile.watchDogTimeout); //Register RSTC_SR = new Register(0xFFFFFE04); //uint count = RSTC_SR.Value; //Debug.Print("RSTC_SR= " + count); //Register WDT_MR = new Register(0xFFFFFE44); //uint wdt = WDT_MR.Value; //Debug.Print("WDT_MR= " + wdt); //Register WDT_SR = new Register(0xFFFFFE48); //uint wdts = WDT_SR.Value; //Debug.Print("WDT_SR= " + wdts); //if (GHI.Processor.Watchdog.Enabled) //{ // Debug.Print("GHI says WDT is ENABLED!!!\r\n"); //} //else //{ // Debug.Print("GHI says WDT is disabled\r\n"); //} //InputPort modePin = new InputPort(GHI.Pins.G400.PA25, false, Port.ResistorMode.PullUp); //bool modePinValue = modePin.Read(); //Create BTConsole btConsole = new BTConsole(); btConsole.OpenConsolePort(); //Set system time EVK7GPS.setSystemTime(EVK7GPS.sendI2CCmd("$PUBX,04*37\r\n")); //Utility.SetLocalTime(RealTimeClock.GetDateTime()); #region STATES cpfState[1] = new InitMission("Init Mission"); cpfState[2] = new InitProfile("Init Profile"); cpfState[3] = new Descend("Descend"); cpfState[4] = new Ascend("Ascend"); cpfState[5] = new SurfaceOpsSetBellows("Surface Ops Set Bellows"); cpfState[6] = new SurfaceOps("Surface Ops"); cpfState[7] = new PreMissionDelay("Pre-Mission Delay"); cpfState[8] = new DumpCPData("Dump CP Data"); cpfState[9] = new ABRetractFast("AB Set Fast"); cpfState[10] = new ABRetractSlow("AB Set Slow"); cpfState[11] = new Park("Park"); cpfState[12] = new Anchor("Anchor"); cpfState[13] = new DeAnchor("DeAnchor"); cpfState[14] = new StartCPMode("Start CP Mode"); cpfState[15] = new RecoveryMode("RecoveryMode"); cpfState[16] = new Exit("Exit"); #endregion CurrentState = CPFStates.initMission; NextState = CurrentState; PastState = (CPFStates)0; //TODO can more initialization be moved into SM (initMission?). Starting SBE41 ASAP can give depth-control. Help protect float from romboot when UW //Start ENGR Logger if (EngrLogger.init()) { sbTemp.Clear(); sbTemp.Append("Engr Logger Initialized"); EngrLogger.writeToColumns(sbTemp); } else { SV.RecoveryMode = true; } SBE41.init(); //This just puts a file on the mass storage device to mark the beginning of a mission to make it easy to spot reboots //EngrLogger.writeMissionStartFile(resetControllerStatusValue); //Create missions sbTemp.Clear(); sbTemp.Append("Reading Mission Configuration File"); EngrLogger.writeToColumns(sbTemp); Mission.createMission(Mission.Missions.mission150mNoHold); //Mission.createMission(Mission.Missions.mission60mHold8); //Mission.createMission(Mission.Missions.mission60mHold8); //Mission.createMission(Mission.Missions.mission60mHold30); Mission.upMission(); //Initialize ports & electronics Elmo.init(); Optode.init(); Thread.Sleep(1000); EVK7GPS.init(); IModem.init(); PTH.init(); //TODO Can move to specific classes PTHTimer = new Timer(new TimerCallback(PTHTimerCallback), null, 0, configFile.PTHSamplePeriod); ADCTimer = new Timer(new TimerCallback(ADCTimerCallback), null, 0, configFile.ADCSamplePeriod); BuoyancyControl.init(); //TODO this should all be moved into CN0254 class, but since ADC will soon be changed, leaving here to make progress for (int i = 0; i < 3; i++) { CN0254Volts = CN0254.scanAll(); #if(FAKE_CN0254_VOLTS) CN0254Volts[0] = 2.5; //bellowsPosition CN0254Volts[1] = 4; //batteryBusVolts #endif bellowsPosition = (CN0254Volts[0] * configFile.cn0254CH0Scale) + configFile.cn0254CH0Offset; batteryBusVolts = (CN0254Volts[1] * configFile.cn0254CH1Scale) + configFile.cn0254CH1Offset; batteryBusAmps = (CN0254Volts[2] * configFile.cn0254CH2Scale) + configFile.cn0254CH2Offset; amps12V = (CN0254Volts[3] * configFile.cn0254CH3Scale) + configFile.cn0254CH3Offset; amps33V = (CN0254Volts[4] * configFile.cn0254CH4Scale) + configFile.cn0254CH4Offset; Thread.Sleep(1000); } processStructQ(); while (missionRun) { try { #if (!DEBUG_NO_STATE_TIMEOUT) ExecutionConstraint.Install(cpfState[(int)CurrentState].ECTimeout, 0); #endif #if (DEBUG_NO_STATE_TIMEOUT) ExecutionConstraint.Install(1000*60*60,0); //60 minute timeout #endif do { SMCycleStartTime = Microsoft.SPOT.Hardware.Utility.GetMachineTime(); if (SV.StateEntry) cpfState[(int)CurrentState].doStateEntryActions(); cpfState[(int)CurrentState].doStateActions(); NextState = cpfState[(int)CurrentState].checkEvents(); processStructQ(); //to simulate problems loopCounter++; if (loopCounter == 30) { //add code here to simulate problems after 30th loop sbTemp.Clear(); } //check CPF health, (potentially) overwrite NextState if problem exists NextState = StateBase.checkGlobalProblems(); if (NextState != CurrentState) cpfState[(int)CurrentState].doExitActions(timedoutFalse); writeSystemStateMessage(); SMCyclePeriod = Microsoft.SPOT.Hardware.Utility.GetMachineTime() - SMCycleStartTime; while ((Microsoft.SPOT.Hardware.Utility.GetMachineTime() - SMCycleStartTime) < configFile.SMSleepPeriod) Thread.Sleep(100); } while (NextState == CurrentState); } catch (Exception currentException) { Debug.Print("Need to handle this exception: " + currentException.ToString()); if (currentException is ConstraintException) { #if (!DEBUG_NO_STATE_TIMEOUT) cpfState[(int)CurrentState].doExitActions(timedoutTrue); NextState = cpfState[(int)CurrentState].doTimeoutAction(); #endif } //All other exceptions are caught here. Default in old code was to go to RecoveryMode, so that's what we do here. else { sbTemp.Clear(); sbTemp.Append("*** Exception in State Machine loop: "); sbTemp.Append(currentException.Message); EngrLogger.writeToColumns(sbTemp); for (int i = 0; i < 5; i++) { btConsole.SendLine(sbTemp); Thread.Sleep(1000); } NextState = CPFStates.recoveryMode; } } ExecutionConstraint.Install(-1, 0); PastState = CurrentState; CurrentState = NextState; } } //TODO move the below two methods to BTConsole, Instrument classes, and StructQueue class //Static variables relevant to queue processor #region Queue Static Variables private static BuoyancyControl.PIDLogValues pidLogValues; private static byte[] dequeueMessage = new byte[256]; private static byte[] pubx04ByteArray = new byte[] { (byte)'P', (byte)'U', (byte)'B', (byte)'X', (byte)',', (byte)'0', (byte)'4', }; private static double simPressure = 0.0; public static double bellowsPosition = double.NaN; public static double batteryBusVolts = double.NaN; public static double batteryBusAmps = double.NaN; public static double amps12V = double.NaN; public static double amps33V = double.NaN; private static double[] CN0254Volts = new double[8]; public static SBE41.LPFResults lpfResults; private static readonly StringBuilder SBE41Header = new StringBuilder("SBE41 Message"); private static readonly StringBuilder unParsedSBE41Header = new StringBuilder("Unparsed SBE41 Message"); private static readonly StringBuilder velPIDHeader = new StringBuilder("Vel PID Values"); private static readonly StringBuilder sbPMQ = new StringBuilder(256); private static readonly StringBuilder sbConsoleCommand = new StringBuilder(32); private static readonly StringBuilder consoleCommandNONE = new StringBuilder("NONE"); private static readonly StringBuilder CN0254Header = new StringBuilder("CN0254 Message"); private static readonly StringBuilder PTHHeader = new StringBuilder("PTH Message"); private static readonly StringBuilder OptodeHeader = new StringBuilder("Optode Message"); private static readonly StringBuilder FLBBHeader = new StringBuilder("FLBB Message"); private static readonly StringBuilder EVK7Header = new StringBuilder("EVK7 GPS Message"); private static readonly StringBuilder IModemHeader = new StringBuilder("A3LA Message"); private static readonly StringBuilder DefaultHeader = new StringBuilder("Unknown Message: "); private static readonly StringBuilder BPError = new StringBuilder("Bellows position exceeds limits, start Emergency Ascend. Pos = "); private static byte[] returnedByteArray = new byte[StructQueue.byteArrayWidth]; private static byte[] sbdwtByteArray = new byte[1024]; public static byte[] pubxByteArray = new byte[512]; private static byte[] sbdwtHeader = new byte[9] { (byte)65, (byte)84, (byte)43, (byte)83, (byte)66, (byte)68, (byte)87, (byte)84, (byte)61 }; // AT+SBDWT= private static DateTime timeNow; private static PTH.PTHData pthData; private static int byteArrayLength = -1; private static int msgLength = 0; private static Random randNum = new Random(); #endregion private static void processStructQ() { while (Program.sQueue.Count > 0) { lock (programLock) { qStructure = sQueue.Dequeue(); } switch (qStructure.qRecordType) { case (StructQueue.QRecordType.SBE41): #region //parse and log except "S>fp" and "SBE41 ...") if ((qStructure.byteArray[0] == 83) && (qStructure.byteArray[1] == 62) && (qStructure.byteArray[2] == 102) && (qStructure.byteArray[3] == 112)) { } else if ((qStructure.byteArray[0] == 83) && (qStructure.byteArray[1] == 66) && (qStructure.byteArray[2] == 69) && (qStructure.byteArray[3] == 32) && (qStructure.byteArray[4] == 52) && (qStructure.byteArray[5] == 49)) { } else { byteArrayLength = Array.IndexOf(qStructure.byteArray, 0); //Parse message, only fp and CP mode PTS responses will return a value, all other messages should return .NaN parsedPressure = SBE41.parse(qStructure.byteArray); if ((parsedPressure > -5) && (parsedPressure < 5000)) { SV.Pressure = parsedPressure; #region OVERRIDE_PRESSURE #if(OVERRIDE_PRESSURE) OVERRIDE_PRESSURE(); #endif #endregion #region SIM_PROFILE #if(SIM_PROFILE) SIM_PROFILE(); #endif #endregion #region ADD_RANDP #if(ADD_RANDP) pressure = pressure + ((randNum.NextDouble() - 0.5) / 500.0); #endif #endregion lpfResults = SBE41.LPFPressure(SV.Pressure); if (SV.RunPVPID) { if (SV.RunPVPID) { pidLogValues = BuoyancyControl.PIDPlatformVelocity(Profile.PVSetPoint, lpfResults.diffVel); if (configFile.verbosityLevel > 2) { EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, velPIDHeader, EngrLogger.ColumnNums.pressure, SV.Pressure, //added by LB 7/24/15 because otherwise plotting PID vals is a pain EngrLogger.ColumnNums.PID_setPoint, pidLogValues.setPoint, EngrLogger.ColumnNums.PID_PV, pidLogValues.PV, EngrLogger.ColumnNums.PID_y1, pidLogValues.y1, EngrLogger.ColumnNums.PID_y2, pidLogValues.y2, EngrLogger.ColumnNums.PID_I, pidLogValues.I, EngrLogger.ColumnNums.PID_v, pidLogValues.v, EngrLogger.ColumnNums.PID_u, pidLogValues.u, EngrLogger.ColumnNums.PID_uCPS, pidLogValues.uCPS); //TODO Should do this in a way that the message is time stamped at the source } } } if (configFile.verbosityLevel > 2) { EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, SBE41Header, EngrLogger.ColumnNums.pressure, SV.Pressure, EngrLogger.ColumnNums.CTDSalinity, qStructure.byteArray, EngrLogger.ColumnNums.platformLPFVel, lpfResults.LPFVel, EngrLogger.ColumnNums.platformDiffVel, lpfResults.diffVel, EngrLogger.ColumnNums.platformLPFAcc, lpfResults.LPFAcc, EngrLogger.ColumnNums.pressureAverage, lpfResults.pressureAverage, EngrLogger.ColumnNums.pressureVariance, lpfResults.pressureVariance); //TODO Should do this in a way that the message is time stamped at the source } } else { //log any non-pressure messages EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, unParsedSBE41Header, EngrLogger.ColumnNums.CTDSalinity, qStructure.byteArray); } } //Check for expected response if (SBE41.waitingForResponse) SBE41.checkResponse(qStructure.byteArray); break; #endregion case (StructQueue.QRecordType.Optode): #region for (int i = 0; i < qStructure.byteArray.Length; i++) { if (qStructure.byteArray[i] == 9) qStructure.byteArray[i] = 44; } EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, OptodeHeader, EngrLogger.ColumnNums.pressure, SV.Pressure, EngrLogger.ColumnNums.TOpt, qStructure.byteArray); //check for expectedResponse anywhere in the SBE41 response message msgLength = qStructure.byteArray.Length; if (Optode.waitingForResponse) { if (msgLength > Optode.expectedResponseLength) { for (int j = 0; j < msgLength - Optode.expectedResponseLength; j++) { for (int k = 0; k < Optode.expectedResponseLength; k++) { if (qStructure.byteArray[j + k] != Optode.expectedResponse[k]) { Optode.gotResponse = false; break; } } } Optode.gotResponse = true; } } break; #endregion case (StructQueue.QRecordType.FLBB): #region timeNow = DateTime.Now; if (Array.IndexOf(qStructure.byteArray, (byte)'\t') > -1) { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); sbTemp.Replace('\t', ','); Array.Clear(qStructure.byteArray, 0, qStructure.byteArray.Length); Array.Copy(UTF8Encoding.UTF8.GetBytes(sbTemp.ToString()), qStructure.byteArray, sbTemp.Length); } EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, FLBBHeader, EngrLogger.ColumnNums.pressure, SV.Pressure, EngrLogger.ColumnNums.FLBB, qStructure.byteArray); break; #endregion case (StructQueue.QRecordType.EVK7): #region //Set system time if message is PUBX,04 if (GHI.Utilities.Arrays.Contains(qStructure.byteArray, pubx04ByteArray) >= 0) { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); EVK7GPS.setSystemTime(sbTemp); } else { if (qStructure.errorCode >= 0) { Array.Clear(pubxByteArray, 0, pubxByteArray.Length); Array.Copy(qStructure.byteArray, pubxByteArray, Array.IndexOf(qStructure.byteArray, 0)); EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, EVK7Header, EngrLogger.ColumnNums.GPS, qStructure.byteArray); } else //If error code is < 0 we've got an error { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); EngrLogger.writeToColumns(sbTemp); } } break; #endregion case (StructQueue.QRecordType.IModem): #region EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, qStructure.timeStamp, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, IModemHeader, EngrLogger.ColumnNums.IModem, qStructure.byteArray); if (SurfaceOps.Substate == 3) { IModem.parseSQ(qStructure.byteArray); } break; #endregion case (StructQueue.QRecordType.PTH): #region //If error code == 0 then get a PTH set of samples if (qStructure.errorCode >= 0) { pthData = PTH.getPTH(); timeNow = DateTime.Now; EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, Program.CurrentState, EngrLogger.ColumnNums.comment, PTHHeader, EngrLogger.ColumnNums.LPS331Pressure, pthData.LPS331Pressure, EngrLogger.ColumnNums.LPS331Temperature, pthData.LPS331Temperature, EngrLogger.ColumnNums.SHT21Humidity, pthData.SHT21Humidity, EngrLogger.ColumnNums.SHT21Temperature, pthData.SHT21Temperature); } else //If error code is < 0 we've got an error { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); EngrLogger.writeToColumns(sbTemp); } break; #endregion case (StructQueue.QRecordType.BTConsole): #region processConsoleCommand(qStructure.byteArray); break; #endregion case (StructQueue.QRecordType.CN0254): #region CN0254Volts = CN0254.scanAll(); timeNow = DateTime.Now; bellowsPosition = (CN0254Volts[0] * configFile.cn0254CH0Scale) + configFile.cn0254CH0Offset; batteryBusVolts = (CN0254Volts[1] * configFile.cn0254CH1Scale) + configFile.cn0254CH1Offset; batteryBusAmps = (CN0254Volts[2] * configFile.cn0254CH2Scale) + configFile.cn0254CH2Offset; amps12V = (CN0254Volts[3] * configFile.cn0254CH3Scale) + configFile.cn0254CH3Offset; amps33V = (CN0254Volts[4] * configFile.cn0254CH4Scale) + configFile.cn0254CH4Offset; if (configFile.verbosityLevel > 5) { EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, Program.CurrentState, EngrLogger.ColumnNums.comment, CN0254Header, EngrLogger.ColumnNums.bellowsPosition, bellowsPosition, EngrLogger.ColumnNums.batteryBusVolts, batteryBusVolts, EngrLogger.ColumnNums.batteryBusAmps, batteryBusAmps, EngrLogger.ColumnNums.Amps12V, amps12V, EngrLogger.ColumnNums.Amps33V, amps33V); } #if(FAKE_CN0254_VOLTS) bellowsPosition = 65.0; batteryBusVolts = 30.0; #endif break; #endregion default: #region timeNow = DateTime.Now; sbTemp.Clear(); sbTemp.Append(DefaultHeader); sbTemp.Append(qStructure.qRecordType); sbTemp.Append(" "); sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, Program.CurrentState, EngrLogger.ColumnNums.comment, UTF8Encoding.UTF8.GetBytes(sbTemp.ToString())); break; #endregion } //sbTemp.Clear(); //sbTemp.Append(UTF8Encoding.UTF8.GetChars(qStructure.byteArray)); //Debug.Print(sbTemp.ToString()); } } public static bool DirectoryValid { get; set; } public static int uploadEngrFileNum = -1; private static void processConsoleCommand(byte[] consoleCommandMessage) { const byte byteToken = 44; int tokenIndex = -1; double argValue = -1; //Ignore command if it doesn't have a CR if (Array.IndexOf(consoleCommandMessage, 13) >= 0) { BTConsole.BTSend = true; sbTemp.Clear(); sbTemp.Append("Processing Console Command: "); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, 0, Array.IndexOf(consoleCommandMessage, 13))); EngrLogger.writeToColumns(sbTemp); //Check if the command has an argument tokenIndex = Array.IndexOf(consoleCommandMessage, byteToken); //If it has an argument, process it here if (tokenIndex > 0) { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, tokenIndex + 1, (Array.IndexOf(consoleCommandMessage, 13) - tokenIndex - 1))); try { argValue = double.Parse(sbTemp.ToString()); sbTemp.Clear(); sbTemp.Append("Console arg value = "); sbTemp.Append(argValue.ToString()); Debug.Print(sbTemp.ToString()); } catch { sbTemp.Clear(); sbTemp.Append("Error parsing console command argument: "); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, 0, (Array.IndexOf(consoleCommandMessage, 13) - 1))); EngrLogger.writeToColumns(sbTemp); } sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, 1, tokenIndex - 1)); switch (sbTemp.ToString().ToUpper()) { case "SIMP": simPressure = argValue; sbTemp.Clear(); sbTemp.Append("Sim P = "); sbTemp.Append(simPressure.ToString()); Debug.Print(sbTemp.ToString()); break; case "UPENGR": SV.UploadEngrFile = true; uploadEngrFileNum = (int)argValue; break; } } else //process commands without an argument { sbTemp.Clear(); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, 1, (Array.IndexOf(consoleCommandMessage, 13) - 1))); switch (sbTemp.ToString().ToUpper()) { case "DIR": break; case "DOWNENGR": break; case "DOWNMIS": break; case "GETDIR": EngrLogger.getDirectory(); DirectoryValid = true; break; case "UPDATA": break; case "GO": SV.SurfaceOpsGo = true; break; case "RECOVERYTRUE": SV.RecoveryMode = true; sbTemp.Clear(); sbTemp.Append("Recovery mode set true"); EngrLogger.writeToColumns(sbTemp); break; case "RECOVERYFALSE": SV.RecoveryMode = false; sbTemp.Clear(); sbTemp.Append("Recovery mode set false"); EngrLogger.writeToColumns(sbTemp); break; case "EXIT": CurrentState = Program.CPFStates.exit; break; case "UPENGR0": SV.UploadEngrFile = true; uploadEngrFileNum = 0; break; case "UPENGR1": SV.UploadEngrFile = true; uploadEngrFileNum = 1; break; case "UPENGR2": SV.UploadEngrFile = true; uploadEngrFileNum = 2; break; case "UPENGR3": SV.UploadEngrFile = true; uploadEngrFileNum = 3; break; case "UPENGR4": SV.UploadEngrFile = true; uploadEngrFileNum = 4; break; case "UPENGR5": SV.UploadEngrFile = true; uploadEngrFileNum = 5; break; case "UPENGR6": SV.UploadEngrFile = true; uploadEngrFileNum = 6; break; case "UPENGR7": SV.UploadEngrFile = true; uploadEngrFileNum = 7; break; case "UPENGR8": SV.UploadEngrFile = true; uploadEngrFileNum = 8; break; case "UPENGR9": SV.UploadEngrFile = true; uploadEngrFileNum = 9; break; #if(OVERRIDE_PRESSURE) case "RANDON": simRAND_ON = true; break; case "RANDOFF": simRAND_ON = false; break; #endif default: sbTemp.Clear(); sbTemp.Append("Invalid command, try again"); btConsole.SendLine(sbTemp); break; } } } else { sbTemp.Clear(); sbTemp.Append("Received non-CR terminated Console Command: "); sbTemp.Append(UTF8Encoding.UTF8.GetChars(consoleCommandMessage, 0, (Array.IndexOf(consoleCommandMessage, 0) - 1))); EngrLogger.writeToColumns(sbTemp); } sbConsoleCommand.Clear(); sbConsoleCommand.Append("NONE"); } private static StructQueue.qStruct PTHQStruct = new StructQueue.qStruct() { qRecordType = StructQueue.QRecordType.PTH, byteArray = new byte[StructQueue.byteArrayWidth] }; private static object PTHTimerLock = new Object(); private static void PTHTimerCallback(object o) { PTHQStruct.timeStamp = DateTime.Now; PTHQStruct.state = CurrentState; PTHQStruct.errorCode = 0; lock (PTHTimerLock) { Program.sQueue.Enqueue(PTHQStruct); } } private static StructQueue.qStruct ADCQStruct = new StructQueue.qStruct() { qRecordType = StructQueue.QRecordType.CN0254, byteArray = new byte[StructQueue.byteArrayWidth] }; private static object ADCTimerLock = new Object(); private static void ADCTimerCallback(object o) { lock (ADCTimerLock) { Program.sQueue.Enqueue(ADCQStruct); } } private static void writeSystemStateMessage() { timeNow = DateTime.Now; sbTemp.Clear(); if (SV.RunPVPID) sbTemp.Append("PID On, "); else sbTemp.Append("PID Off, "); if (Elmo.extending) sbTemp.Append("Ext'g, "); if (Elmo.retracting) sbTemp.Append("Ret'g, "); if (Elmo.motorStopped) sbTemp.Append("Stopped, "); if (CurrentState == CPFStates.park) sbTemp.Append("Park, "); sbTemp.Append("Scend sub: "); sbTemp.Append(Profile.ProfileState); sbTemp.Append(", "); sbTemp.Append("depthNum = "); sbTemp.Append(SV.PressureTableNum.ToString()); EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, Program.CurrentState, EngrLogger.ColumnNums.comment, sbTemp, EngrLogger.ColumnNums.pressure, SV.Pressure, EngrLogger.ColumnNums.bellowsPosition, bellowsPosition, EngrLogger.ColumnNums.batteryBusVolts, batteryBusVolts, EngrLogger.ColumnNums.batteryBusAmps, batteryBusAmps, EngrLogger.ColumnNums.Amps12V, amps12V); } #region NO_CTD #if(NO_CTD) OVERRIDE_PRESSURE(); #endif #endregion #region TESTS #region OVERRIDE_PRESSURE #if(OVERRIDE_PRESSURE) private static bool simRAND_ON = true; private static void OVERRIDE_PRESSURE() { if (simRAND_ON) SV.Pressure = simPressure + ((randNum.NextDouble() - 0.5) / 10.0); else SV.Pressure = simPressure; SV.runPVPID = false; sbTemp.Clear(); sbTemp.Append("Simulating pressure from console, runPVPID: false, P = "); sbTemp.Append(pressure.ToString("f2")); Debug.Print(sbTemp.ToString()); } #endif #endregion #endregion } }