//#define OVERRIDE_PRESSURE //#define NO_CTD #define DEBUG_ANNOUNCE #define FAKE_CN0254_VOLTS #define DEBUG_NO_STATE_TIMEOUT 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, emergencyAscend, cpfStatesLength } public static StateBase[] cpfState = new StateBase[(int)CPFStates.cpfStatesLength]; public static CPFStates CurrentState { get; protected set; } public static CPFStates PastState { get; protected set; } public static CPFStates NextState { get; protected set; } public static I2CDevice g400I2C = new I2CDevice(null); private static Object programLock = new Object(); private static Timer PTHTimer; private static Timer ADCTimer; 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 void Main() { Debug.Print("Program Started"); //Open COM port first thing for debug output 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 EmergencyAscend("Emergency Ascend"); #endregion CurrentState = CPFStates.initMission; NextState = CurrentState; PastState = (CPFStates)0; //Start ENGR Logger if (EngrLogger.init()) { sbTemp.Clear(); sbTemp.Append("Engr Logger Initialized"); EngrLogger.writeToColumns(sbTemp); } else { SV.SORecoveryMode = true; } //Create missions Mission.createMission(Mission.Missions.mission60mHold8); Mission.upMission(); //Initialize ports & electronics Elmo.init(); Optode.init(); Thread.Sleep(2000); //Sleep present in legacy code EVK7GPS.init(); IModem.init(); Thread.Sleep(3000); //Sleep present in legacy code PTH.init(); PTHTimer = new Timer(new TimerCallback(PTHTimerCallback), null, 0, configFile.PTHSamplePeriod); ADCTimer = new Timer(new TimerCallback(ADCTimerCallback), null, 0, configFile.ADCSamplePeriod); BuoyancyControl.init(); SBE41.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 (true) { 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 { if (SV.StateEntry) cpfState[(int)CurrentState].doStateEntryActions(); cpfState[(int)CurrentState].doStateActions(); NextState = cpfState[(int)CurrentState].checkEvents(); processStructQ(); //check CPF health, overwrite NextState if problem present NextState = StateBase.checkGlobalProblems(); if (NextState != CurrentState) cpfState[(int)CurrentState].doExitActions(false); writeSystemStateMessage(); Thread.Sleep(2000); } 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(true); NextState = cpfState[(int)CurrentState].doTimeoutAction(); #endif } //Need to handle other exceptions here } 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 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 byteArrayLength = Array.IndexOf(qStructure.byteArray, 0); //check for pressure only message from SBE41. This means message starts with a blank space and 8<=length=>10 if ((qStructure.byteArray[0] == 32) && (byteArrayLength <= 10) && (byteArrayLength >= 8)) { SV.Pressure = SBE41.parsePOnly(qStructure.byteArray); #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) SV.Pressure = SV.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.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 only messages except "S>fp") 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 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.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; EngrLogger.writeToColumns(EngrLogger.ColumnNums.dateTime, timeNow, EngrLogger.ColumnNums.state, qStructure.state, EngrLogger.ColumnNums.comment, FLBBHeader, EngrLogger.ColumnNums.FLBB, qStructure.byteArray); break; #endregion case (StructQueue.QRecordType.EVK7): #region //If error code == 0 then get a PTH set of samples 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; } } 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.SORecoveryMode = true; sbTemp.Clear(); sbTemp.Append("Recovery mode set true"); EngrLogger.writeToColumns(sbTemp); break; case "RECOVERYFALSE": SV.SORecoveryMode = false; sbTemp.Clear(); sbTemp.Append("Recovery mode set false"); EngrLogger.writeToColumns(sbTemp); break; //case "EXIT": // CPFState = CPFStates.Exit; // break; case "UPENGR0": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 0; break; case "UPENGR1": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 1; break; case "UPENGR2": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 2; break; case "UPENGR3": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 3; break; case "UPENGR4": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 4; break; case "UPENGR5": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 5; break; case "UPENGR6": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 6; break; case "UPENGR7": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 7; break; case "UPENGR8": BTConsole.uploadEngrFile = true; uploadEngrFileNum = 8; break; case "UPENGR9": BTConsole.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 } }