Example #1
0
        public static void PacketGroundSensor(Packet Packet)
        {
            if (Packet == null || Packet.Data == null || Packet.Data.Payload == null || Packet.Data.Payload.Length != 40)
            {
                Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Ground sensor packet invalid. Discarding. Length: " + Packet?.Data?.Payload?.Length);
                return;
            }
            DateTime Timestamp        = DateTime.Now;
            int      UVLight          = UtilData.ToInt(UtilMain.SubArray(Packet.Data.Payload, 0, 4));
            float    AirQuality       = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 4, 4));
            float    SoilMoist        = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 8, 4));
            uint     ThermocoupleData = UtilData.ToUInt(UtilMain.SubArray(Packet.Data.Payload, 12, 4));
            double   AtmoTemp         = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 16, 8));
            double   AtmoPres         = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 24, 8));
            double   AtmoHumid        = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 32, 8));

            UV.Data.Add(new Datum <int>(Timestamp, UVLight));
            AirPollution.Data.Add(new Datum <float>(Timestamp, AirQuality));
            SoilMoisture.Data.Add(new Datum <float>(Timestamp, SoilMoist));
            ThermoExt.Data.Add(new Datum <float>(Timestamp, MAX31855.ConvertExternalFromRaw(ThermocoupleData)));
            ThermoInt.Data.Add(new Datum <float>(Timestamp, MAX31855.ConvertInternalFromRaw(ThermocoupleData)));
            AirTemp.Data.Add(new Datum <double>(Timestamp, AtmoTemp));
            AirPressure.Data.Add(new Datum <double>(Timestamp, AtmoPres));
            AirHumidity.Data.Add(new Datum <double>(Timestamp, AtmoHumid));
        }
Example #2
0
        public static void ParseRailTargetPacket(Packet Packet)
        {
            if (CheckPacket(Packet, 5, "Rail Target"))
            {
                float TargetDist = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 1, 4));
                switch (Packet.Data.Payload[0])
                {
                case 0x00:
                    RoverMain.IOHandler.RailController.GotoTop();
                    break;

                case 0x01:
                    RoverMain.IOHandler.RailController.GotoDrillGround();
                    break;

                case 0x02:
                    RoverMain.IOHandler.RailController.TargetLocation         = TargetDist;
                    RoverMain.IOHandler.RailController.TargetLocationRefIsTop = true;
                    break;

                case 0x03:
                    RoverMain.IOHandler.RailController.TargetLocation         = TargetDist;
                    RoverMain.IOHandler.RailController.TargetLocationRefIsTop = false;
                    break;
                }
            }
        }
Example #3
0
        static void Main(string[] args)
        {
            Log.SetGlobalOutputLevel(Log.Severity.INFO);
            Log.SetSingleOutputLevel(Log.Source.NETWORK, Log.Severity.DEBUG);
            Log.ErrorCodes  = ScienceErrors.ERROR_CODES;
            Log.SystemNames = ScienceErrors.SYSTEMS;
            Log.Begin();
            Log.ForceOutput(Log.Severity.INFO, Log.Source.OTHER, "Science Station - Base Side");

            byte[] StrB    = UtilData.ToBytes("Erza-{}'");
            byte[] Fail    = new byte[] { 0x8C };
            bool   Success = UtilData.TryToString(Fail, out string Str);

            if (Success)
            {
                Console.WriteLine(Str);
            }
            else
            {
                Console.WriteLine(UtilMain.BytesToNiceString(StrB, true));
            }

            MainWindow Main = new MainWindow();

            Application.EnableVisualStyles();
            Server.ClientConnectionChange += Main.UpdateClientList;
            Application.Run(Main);
        }
Example #4
0
 /// <summary> Sets the timestamp. Must be 4 or more bytes (only first 4 used). </summary>
 /// <param name="Time"> The new timestamp. </param>
 public void SetTime(byte[] Time)
 {
     if (Time.Length < 4)
     {
         throw new ArgumentException("Timestamp must be 4 bytes.");
     }
     this.Timestamp = UtilMain.SubArray(Time, 0, 4);
 }
Example #5
0
 private void DataTextbox_TextChanged(object sender, EventArgs e)
 {
     try
     {
         byte[] Data = InterpretInput(this.DataTextbox.Text.ToCharArray());
         this.InterpretationData.Text = "0x" + UtilMain.BytesToNiceString(Data, true);
     }
     catch { this.InterpretationData.Text = "Unknown"; }
 }
Example #6
0
 /// <summary> Checks if the device is responding by querying a known, constant register value. </summary>
 public bool Test()
 {
     byte[] DeviceData = Read((byte)Register.DEV_ID, 1);
     if (this.TraceLogging)
     {
         Log.Trace(this, "Testing returned " + UtilMain.BytesToNiceString(DeviceData, false) + ", expected 0x60.");
     }
     return((DeviceData != null) && (DeviceData.Length > 0) && (DeviceData[0] == 0x60));
 }
Example #7
0
 private void IDTextbox_TextChanged(object sender, EventArgs e)
 {
     try
     {
         byte[] ID = UtilMain.StringToBytes(this.IDTextbox.Text);
         this.InterpretationID.Text = "0x" + UtilMain.BytesToNiceString(new byte[] { ID.Last() }, false);
     }
     catch { this.InterpretationID.Text = "Unknown"; }
 }
Example #8
0
 public static void ParseServoPacket(Packet Packet)
 {
     if (CheckPacket(Packet, 5, "Servo Set"))
     {
         if (Packet.Data.Payload[0] == 0x00) // Sample Door
         {
             RoverMain.IOHandler.DrillController.DoorOpen = (UtilData.ToInt(UtilMain.SubArray(Packet.Data.Payload, 1, 4)) == 1);
         }
     }
 }
Example #9
0
 public static void PacketTesting(Packet Packet)
 {
     if (Packet == null || Packet.Data == null || Packet.Data.Payload == null || Packet.Data.Payload.Length != 12)
     {
         Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "System sensor packet invalid. Discarding. Length: " + Packet?.Data?.Payload?.Length);
         return;
     }
     int      Enc    = UtilData.ToInt(UtilMain.SubArray(Packet.Data.Payload, 0, 4));
     DateTime Sample = new DateTime(UtilData.ToLong(UtilMain.SubArray(Packet.Data.Payload, 4, 8)));
 }
Example #10
0
        private T LastValue; // Last filter value (internal use)

        /// <summary>
        /// Constructs a low pass filter with
        /// time constant <c>LPFk</c>.</summary>
        /// <param name="LPFk">
        /// Low Pass Filter Time Constant.</param>
        public LowPass(double LPFk = 0.25)
        {
            if (!UtilMain.IsNumericType(typeof(T)))
            {
                throw new ArgumentException("Cannot create filter of non-numeric type: " + typeof(T).ToString());
            } // We can now assert that T is a numeric

            this.Output = default(T);
            this.LPFk   = LPFk;
            this.Reset();
        }
Example #11
0
        public IPEndPoint From;  // Endpoint that the message was received from.

        /// <summary>
        /// Constructs a message given
        /// incoming data.
        /// Data encoded with:
        /// Timestamp data[0] to data[3]
        /// ID at data[4]
        /// Data encoded after data[4], i.e. data[5:]
        /// </summary>
        /// <param name="IncomingData">
        /// Incoming data array</param>
        /// <param name="From">
        /// Given from endpoint</param>
        public Message(byte[] IncomingData, IPEndPoint From)
        {
            // Retrieve necessary data for instantiation
            byte[] TimeBytes  = UtilMain.SubArray(IncomingData, 0, 4);
            byte   IdByte     = IncomingData[4];
            int    DataLength = IncomingData.Length - 4;

            // Set Instance Variables
            this.Data     = UtilMain.SubArray(IncomingData, 5, DataLength - 1);
            this.Id       = (int)IdByte;
            this.Timesamp = UtilMain.ByteArrayToInt(TimeBytes);
            this.From     = From;
        }
Example #12
0
        /// <summary> Formats the Messages's contents to be human-readable. </summary>
        public override string ToString()
        {
            StringBuilder Str = new StringBuilder();

            Str.Append("Packet = Time:(0x");
            Str.Append(UtilMain.BytesToNiceString(this.Timestamp, false));
            Str.Append(") ID:(0x");
            Str.Append(this.ID.ToString("X2"));
            Str.Append(") Data:(0x");
            Str.Append(UtilMain.BytesToNiceString(this.Payload, true));
            Str.Append(')');
            return(Str.ToString());
        }
Example #13
0
 private byte[] Read(byte Register, byte Length)
 {
     if (this.IsSPI)
     {
         byte[] DataOut = new byte[Length + 1];
         DataOut[0] = (byte)((Register & 0b0111_1111) | 0b1000_0000);
         byte[] DataIn = this.SPIBus.Write(this.SPICS, DataOut, DataOut.Length);
         return(UtilMain.SubArray(DataIn, 1, Length));
     }
     else
     {
         return(this.I2CBus.ReadRegister(this.I2CAddress, Register, Length));
     }
 }
Example #14
0
                    Iterations;         // Number of iterations in the filter

        /// <summary>
        /// Construct an average filter with
        /// given roll-length.
        /// </summary>
        /// <param name="FilterCount">
        /// Roll length for the average filter.</param>
        public Average(int FilterCount = 10)
        {
            if (!UtilMain.IsNumericType(typeof(T)))
            {
                throw new ArgumentException("Cannot create filter of non-numeric type: " + typeof(T).ToString());
            } // We can now assert that T is a numeric type

            this.Output       = default(T);
            this.CurSum       = 0;
            this.Index        = 0;
            this.Iterations   = 0;
            this.FilterCount  = FilterCount;
            this.AverageArray = new dynamic[this.FilterCount];
            this.InitializeArray(); // Initialize average array to defaults
        }
Example #15
0
        /// <summary> Does a 12b read/write with the specified command. </summary>
        /// <param name="Command"> The command (4 MSb) to send. </param>
        /// <param name="Data"> The data (12 LSb) to send. </param>
        /// <param name="Long"> Whether to send out additional SCLK pulses for the ADC to do sampling. </param>
        /// <returns> The 12b data returned by the device. </returns>
        private ushort DoCommand(Command Command, ushort Data = 0x000, bool Long = false)
        {
            byte[] DataOut;
            if (!Long)
            {
                DataOut = new byte[2];
            }                                     // Regular command, no sampling.
            else
            {
                switch (this.Config.ConversionClockSrc) // We are doing sampling, determine the correct number of SCLKs.
                {
                case ConversionClockSrc.SCLK:
                    DataOut = (this.Config.UseLongSample ? new byte[2 + 4] : new byte[2 + 2]);
                    break;

                case ConversionClockSrc.SCLK_HALF:
                    DataOut = (this.Config.UseLongSample ? new byte[2 + 7] : new byte[2 + 4]);
                    break;

                case ConversionClockSrc.SCLK_QUARTER:
                    DataOut = (this.Config.UseLongSample ? new byte[2 + 14] : new byte[2 + 7]);
                    break;

                case ConversionClockSrc.INTERNAL: // We are assuming the time between The two SPI transactions is at least 4us for short, or 8us for long sampling. This seems to always be true on the Pi, but is not guaranteed.
                    DataOut = new byte[2];        // No need for additional SCLKs.
                    break;

                default:
                    DataOut = new byte[2];
                    break;
                }
            }

            DataOut[0] = (byte)((((byte)Command << 4) & 0b1111_0000) | ((Data >> 8) & 0b0000_1111));
            DataOut[1] = (byte)(Data & 0b1111_1111);
            if (this.TraceLogging)
            {
                Log.Trace(this, "Sending command: " + UtilMain.BytesToNiceString(DataOut, true));
            }
            byte[] DataIn = this.Bus.Write(this.CS, DataOut, DataOut.Length);
            if (this.TraceLogging)
            {
                Log.Trace(this, "Received: " + UtilMain.BytesToNiceString(DataIn, true));
            }
            return((ushort)(Command == Command.READ_CONF ?
                            (((DataIn[0] & 0b0000_1111) << 8) | (DataIn[1])) :
                            (DataIn[0] << 4) | ((DataIn[1] & 0b1111_0000) >> 4)));
        }
Example #16
0
        public static void PacketRailStatus(Packet Packet)
        {
            if (Packet == null || Packet.Data == null || Packet.Data.Payload == null || Packet.Data.Payload.Length != 17)
            {
                Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Rail status packet invalid. Discarding. Length: " + Packet?.Data?.Payload?.Length);
                return;
            }

            byte  Status       = Packet.Data.Payload[0];
            float RailSpeed    = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 1, 4));
            float DepthTop     = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 5, 4));
            float HeightGround = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 9, 4));
            float Target       = UtilData.ToFloat(UtilMain.SubArray(Packet.Data.Payload, 13, 4));

            BaseMain.Window.UpdateRail(RailSpeed, DepthTop, HeightGround, Target, ((Status & 0b100) == 0b100), ((Status & 0b10) == 0b10), ((Status & 0b1) == 0b1));
        }
Example #17
0
        public byte[] Payload;    // Stored message data (discluding timestamp and ID)

        /// <summary>
        /// Constructs a message given raw data, likes when received via network.
        /// Data encoded as such:
        /// Timestamp: RawData[0] through RawData[3]
        /// ID: RawData[4]
        /// Payload: Remainder (RawData[5] though end)
        /// </summary>
        /// <param name="RawData"> Incoming data array </param>
        public Message(byte[] RawData)
        {
            if (RawData.Length < 5)
            {
                throw new ArgumentException("Raw data not sufficient for packet. Must be at least 5 bytes long.");
            }
            this.Timestamp = UtilMain.SubArray(RawData, 0, 4);
            this.ID        = RawData[4];
            if (RawData.Length > 5)
            {
                this.Payload = UtilMain.SubArray(RawData, 5, RawData.Length - 5);
            }
            else
            {
                this.Payload = new byte[0];
            }
        }
Example #18
0
        private byte[] InterpretInput(char[] Input)
        {
            if (!Input.Contains('"'))
            {
                return(UtilMain.StringToBytes(new string(Input)).Reverse().ToArray());
            }
            int LocOfStart = Array.IndexOf(Input, '"');
            int StrLen     = Array.IndexOf(Input.Skip(LocOfStart + 1).ToArray(), '"');

            char[]      BeforeChars = Input.Take(LocOfStart).ToArray();
            List <byte> Output      = new List <byte>();

            Output.AddRange(UtilMain.StringToBytes(new string(BeforeChars)).Reverse().ToArray());
            string Str = new string(Input.Skip(LocOfStart + 1).Take(StrLen).ToArray());

            Output.AddRange(UtilData.ToBytes(Str));
            Output.AddRange(InterpretInput(Input.Skip(LocOfStart + StrLen + 2).ToArray()));
            return(Output.ToArray());
        }
Example #19
0
 private void SendPacketBtn_Click(object sender, EventArgs e)
 {
     try
     {
         byte[] Timestamp = UtilMain.StringToBytes(this.TimestampTextbox.Text).Reverse().ToArray();
         byte   ID        = UtilMain.StringToBytes(this.IDTextbox.Text)[0];
         byte[] Data      = InterpretInput(this.DataTextbox.Text.ToCharArray());
         Packet Pack      = new Packet(ID, this.SendAsUDP.Checked, this.ClientSelector.SelectedItem.ToString());
         Log.Output(Log.Severity.DEBUG, Log.Source.NETWORK, "Sending packet with data length: " + Data.Length);
         Pack.AppendData(Data);
         Server.Send(Pack);
         Log.Output(Log.Severity.INFO, Log.Source.GUI, "Sending custom packet: " + Pack.ToString());
     }
     catch (Exception Exc)
     {
         Log.Output(Log.Severity.ERROR, Log.Source.NETWORK, "Something went wrong while sending custom packet.");
         Log.Exception(Log.Source.NETWORK, Exc);
     }
 }
Example #20
0
        public static void PacketSysSensor(Packet Packet)
        {
            if (Packet == null || Packet.Data == null || Packet.Data.Payload == null || Packet.Data.Payload.Length != 40)
            {
                Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "System sensor packet invalid. Discarding. Length: " + Packet?.Data?.Payload?.Length);
                return;
            }
            double SysA   = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 0, 8));
            double DrillA = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 8, 8));
            double RailA  = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 16, 8));
            double SysV   = UtilData.ToDouble(UtilMain.SubArray(Packet.Data.Payload, 24, 8));

            DateTime Sample = new DateTime(UtilData.ToLong(UtilMain.SubArray(Packet.Data.Payload, 32, 8)));

            //Log.Output(Log.Severity.INFO, Log.Source.GUI, "Got sysA:" + SysCurrent + ", DrlA:" + DrillCurrent + ", SysV:" + SysVoltage);
            BaseMain.Window.UpdateGauges(SysV, SysA, DrillA, RailA);
            SupplyVoltage.Data.Add(new Datum <double>(Sample, SysV));
            SystemCurrent.Data.Add(new Datum <double>(Sample, SysA));
            DrillCurrent.Data.Add(new Datum <double>(Sample, DrillA));
            RailCurrent.Data.Add(new Datum <double>(Sample, RailA));
        }
Example #21
0
        public double Qbias;         // Process noise variance for the signal rate bias.

        /// Kalman Filter Constructor
        /// <summary>
        /// Handles construction of the
        /// Kalman filter with default
        /// filter coefficients.
        /// See class comment for more
        /// information regarding
        /// implementation.</summary>
        public Kalman()
        {
            if (!UtilMain.IsNumericType(typeof(T))) // Can now assert that T is a numeric
            {
                throw new ArgumentException("Cannot create filter of non-numeric type: " + typeof(T).ToString());
            }

            this.Output      = default(T);
            this.LastRate    = default(T);
            this.StopWatch   = new Stopwatch();
            this.Initialized = false;
            this.Q           = 0.001; // Default Q value (arbitrary), set Q to necessary value
            this.Qbias       = 0.003; // Default Qbias value (arbitrary), set Qbias to necessary value
            this.Rmeasure    = 0.03;  // Default Rmeasure value (arbitrary), set Rmeasure to necessary value
            this.CalcMeasure = 0.0;
            this.Bias        = 0.0;
            this.P           = new double[2, 2];
            this.K           = new double[2];
            this.P[0, 0]     = 0.0; // Since we assume that the bias is 0 and we know the starting position,
            this.P[0, 1]     = 0.0; // the error covariance matrix is set like so.
            this.P[1, 0]     = 0.0;
            this.P[1, 1]     = 0.0;
        }
Example #22
0
 private void UpdateTime()
 {
     this.TimestampTextbox.Text = UtilMain.BytesToNiceString(Packet.GetCurrentTime(), true);
 }
Example #23
0
        public static void Start(string[] args)
        {
            if (args.Length < 3)
            {
                TestMain.ErrorExit("io bbb command requires functionality to test.");
            }
            BeagleBone.Initialize(SystemMode.DEFAULT, true);

            switch (args[2].ToLower())
            {
            case "digin":
            {
                if (args.Length < 4)
                {
                    TestMain.ErrorExit("io bbb digin command requires pin to test.");
                }
                BBBPin InputPin = StringToPin(args[3]);
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Testing digital input on BBB pin " + InputPin.ToString());
                BBBPinManager.AddMappingGPIO(InputPin, false, ResistorState.PULL_DOWN);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IDigitalIn Input = new DigitalInBBB(InputPin);
                while (true)
                {
                    Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Current pin state: " + (Input.GetInput() ? "HIGH" : "LOW"));
                    Thread.Sleep(250);
                }
            }

            case "digout":
            {
                if (args.Length < 4)
                {
                    TestMain.ErrorExit("io bbb digout command requires pin to test.");
                }
                BBBPin OutputPin = StringToPin(args[3]);
                if (args.Length < 5)
                {
                    TestMain.ErrorExit("io bbb digout command requires output mode (high/low/blink).");
                }
                if (args[4] != "high" && args[4] != "low" && args[4] != "blink")
                {
                    TestMain.ErrorExit("Invalid digout test mode supplied.");
                }
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Testing digital output on BBB pin " + OutputPin.ToString());
                BBBPinManager.AddMappingGPIO(OutputPin, true, ResistorState.PULL_DOWN);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IDigitalOut Output = new DigitalOutBBB(OutputPin);
                if (args[4] == "high")
                {
                    Output.SetOutput(true);
                }
                else if (args[4] == "low")
                {
                    Output.SetOutput(false);
                }
                else
                {
                    bool Out = false;
                    while (true)
                    {
                        Output.SetOutput(Out);
                        Out = !Out;
                        Thread.Sleep(250);
                    }
                }
                break;
            }

            case "pwm":
            {
                if (args.Length < 4)
                {
                    TestMain.ErrorExit("io bbb pwm command requires pin to test.");
                }
                BBBPin OutputPin = StringToPin(args[3]);
                if (args.Length < 5)
                {
                    TestMain.ErrorExit("io bbb pwm command requires frequency.");
                }
                int Frequency = int.Parse(args[4]);
                if (args.Length < 6)
                {
                    TestMain.ErrorExit("io bbb pwm command requires output mode.");
                }
                if (args[5] != "per" && args[5] != "sine")
                {
                    TestMain.ErrorExit("io bbb pwm command invalid (per/sine).");
                }
                if (args[5] == "per" && args.Length < 7)
                {
                    TestMain.ErrorExit("io bbb pwm per must be provided duty cycle.");
                }
                BBBPinManager.AddMappingPWM(OutputPin);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IPWMOutput Output = PWMBBB.GetFromPin(OutputPin);
                Output.SetFrequency(Frequency);
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Testing PWM output on BBB pin " + OutputPin.ToString() + " at " + Frequency + "Hz.");
                if (args[5] == "per")
                {
                    Output.SetOutput(int.Parse(args[6]) / 100F);
                    Output.SetEnabled(true);
                    Thread.Sleep(15000);     // Not sure if it stops outputting when the program exits.
                }
                else
                {
                    int Cycle = 0;
                    while (true)
                    {
                        float Val = (float)((Math.Sin(Cycle * Math.PI / 180.000D) + 1) / 2);
                        Output.SetOutput(Val);
                        Thread.Sleep(50);
                        Cycle += 20;
                    }
                }
                break;
            }

            case "adc":
            {
                if (args.Length < 4)
                {
                    TestMain.ErrorExit("io bbb adc command requires pin to test.");
                }
                BBBPin InputPin = StringToPin(args[3]);
                BBBPinManager.AddMappingADC(InputPin);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IAnalogueIn Input = new AnalogueInBBB(InputPin);
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Testing analogue input on BBB pin " + InputPin.ToString());
                while (true)
                {
                    Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "ADC Input: " + Input.GetInput() + " (Raw: " + Input.GetRawInput() + ")");
                    Thread.Sleep(250);
                }
            }

            case "int":
            {
                if (args.Length < 4)
                {
                    TestMain.ErrorExit("io bbb int command requires pin to test.");
                }
                BBBPin InputPin = StringToPin(args[3]);
                if (args.Length < 5)
                {
                    TestMain.ErrorExit("io bbb int command requires interrupt mode (rise/fall/both).");
                }
                if (args[4] != "rise" && args[4] != "fall" && args[4] != "both")
                {
                    TestMain.ErrorExit("Invalid interrupt mode supplied.");
                }

                BBBPinManager.AddMappingGPIO(InputPin, true, ResistorState.PULL_DOWN);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IDigitalIn Input = new DigitalInBBB(InputPin);
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Testing interrupts on BBB pin " + InputPin.ToString());
                switch (args[4])
                {
                case "rise": ((IInterruptSource)Input).RegisterInterruptHandler(GetInterrupt, InterruptType.RISING_EDGE); break;

                case "fall": ((IInterruptSource)Input).RegisterInterruptHandler(GetInterrupt, InterruptType.FALLING_EDGE); break;

                case "both": ((IInterruptSource)Input).RegisterInterruptHandler(GetInterrupt, InterruptType.ANY_EDGE); break;
                }
                while (true)
                {
                    Thread.Sleep(50);
                }                                     // Program needs to be running to receive.
            }

            case "mtk3339":
            {
                BBBPinManager.AddMappingUART(BBBPin.P9_24);
                BBBPinManager.AddMappingUART(BBBPin.P9_26);
                BBBPinManager.ApplyPinSettings(BBBPinManager.ApplicationMode.APPLY_REGARDLESS);
                IUARTBus UART = UARTBBB.UARTBus1;
                Log.Output(Log.Severity.INFO, Log.Source.HARDWAREIO, "Press any key to stop.");
                while (Console.KeyAvailable)
                {
                    Console.ReadKey();
                }
                byte[] Buffer = new byte[32];
                while (true)
                {
                    Thread.Sleep(10);
                    if (UART.BytesAvailable() > 0)
                    {
                        int Count = UART.Read(32, Buffer);
                        Console.Write(System.Text.Encoding.ASCII.GetString(UtilMain.SubArray(Buffer, 0, Count)));
                    }
                    if (Console.KeyAvailable)
                    {
                        break;
                    }
                }
                break;
            }
            }
        }