Beispiel #1
0
        /// <summary>
        /// Main run loop for incoming traffic.  Runs in its own thread.
        /// <para>
        /// Marking this thread virtual causes tests to randomly fail :-(
        /// </para>
        /// </summary>
        public void run()
        {
            // should set to highest priority
            int arg1;
            int arg2;
            int numPins;
            int size;

            byte[] data;

            try
            {
                // this was while(true) in the java code
                while (true)
                {
                    CancelTokenSource_.Token.ThrowIfCancellationRequested();
                    arg1 = readByte();
                    LOG.Debug("T:" + IncomingTask_.Id + " Processing reply Type " + arg1.ToString("X"));
                    switch (arg1)
                    {
                    case (int)IOIOProtocolCommands.ESTABLISH_CONNECTION:
                        if (readByte() != 'I' || readByte() != 'O' || readByte() != 'I' ||
                            readByte() != 'O')
                        {
                            throw new IOException("Bad establish connection magic");
                        }
                        byte[] hardwareId   = readBytes(8);
                        byte[] bootloaderId = readBytes(8);
                        byte[] firmwareId   = readBytes(8);

                        Handler_.HandleEstablishConnection(hardwareId, bootloaderId, firmwareId);
                        break;

                    case (int)IOIOProtocolCommands.SOFT_RESET:
                        // why only analog pins?
                        AnalogFramePins_.Clear();
                        Handler_.HandleSoftReset();
                        break;

                    case (int)IOIOProtocolCommands.REPORT_DIGITAL_IN_STATUS:
                        // Pin number and state are in same byte
                        arg1 = readByte();
                        Handler_.HandleReportDigitalInStatus(arg1 >> 2, (arg1 & 0x01) == 1);
                        break;

                    case (int)IOIOProtocolCommands.SET_CHANGE_NOTIFY:
                        // Pin number and state are in same byte
                        arg1 = readByte();
                        Handler_.HandleSetChangeNotify(arg1 >> 2, (arg1 & 0x01) == 1);
                        break;

                    case (int)IOIOProtocolCommands.REGISTER_PERIODIC_DIGITAL_SAMPLING:
                        // TODO: implement
                        break;

                    case (int)IOIOProtocolCommands.REPORT_PERIODIC_DIGITAL_IN_STATUS:
                        // TODO: implement
                        break;

                    case (int)IOIOProtocolCommands.REPORT_ANALOG_IN_FORMAT:
                        numPins = readByte();
                        NewFramePins_.Clear();
                        for (int i = 0; i < numPins; ++i)
                        {
                            NewFramePins_.Add(readByte());
                        }
                        calculateAnalogFrameDelta();
                        foreach (int i in RemovedPins_)
                        {
                            Handler_.HandleAnalogPinStatus(i, false);
                        }
                        foreach (int i in AddedPins_)
                        {
                            Handler_.HandleAnalogPinStatus(i, true);
                        }
                        break;

                    case (int)IOIOProtocolCommands.REPORT_ANALOG_IN_STATUS:
                        numPins = AnalogFramePins_.Count();
                        int header = 0;
                        AnalogPinValues_.Count();
                        for (int i = 0; i < numPins; ++i)
                        {
                            if (i % 4 == 0)
                            {
                                header = readByte();
                            }
                            AnalogPinValues_.Add((readByte() << 2) | (header & 0x03));
                            header >>= 2;
                        }
                        Handler_.HandleReportAnalogInStatus(AnalogFramePins_, AnalogPinValues_);
                        break;

                    case (int)IOIOProtocolCommands.UART_REPORT_TX_STATUS:
                        arg1 = readByte();
                        arg2 = readByte();
                        Handler_.HandleUartReportTxStatus(arg1 & 0x03, (arg1 >> 2) | (arg2 << 6));
                        break;

                    case (int)IOIOProtocolCommands.UART_DATA:
                        arg1 = readByte();
                        size = (arg1 & 0x3F) + 1;
                        // HACK HACK HACK while troubleshooting a buffer issue
                        // size = 1;
                        data = readBytes(size);
                        Handler_.HandleUartData(arg1 >> 6, size, data);
                        break;

                    case (int)IOIOProtocolCommands.UART_STATUS:
                        arg1 = readByte();
                        if ((arg1 & 0x80) != 0)
                        {
                            Handler_.HandleUartOpen(arg1 & 0x03);
                        }
                        else
                        {
                            Handler_.HandleUartClose(arg1 & 0x03);
                        }
                        break;

                    case (int)IOIOProtocolCommands.SPI_DATA:
                        arg1 = readByte();
                        arg2 = readByte();
                        size = (arg1 & 0x3F) + 1;
                        data = readBytes(size);
                        Handler_.HandleSpiData(arg1 >> 6, arg2 & 0x3F, data, size);
                        break;

                    case (int)IOIOProtocolCommands.SPI_REPORT_TX_STATUS:
                        arg1 = readByte();
                        arg2 = readByte();
                        Handler_.HandleSpiReportTxStatus(arg1 & 0x03, (arg1 >> 2) | (arg2 << 6));
                        break;

                    case (int)IOIOProtocolCommands.SPI_STATUS:
                        arg1 = readByte();
                        if ((arg1 & 0x80) != 0)
                        {
                            Handler_.HandleSpiOpen(arg1 & 0x03);
                        }
                        else
                        {
                            Handler_.HandleSpiClose(arg1 & 0x03);
                        }
                        break;

                    case (int)IOIOProtocolCommands.I2C_STATUS:
                        arg1 = readByte();
                        if ((arg1 & 0x80) != 0)
                        {
                            Handler_.HandleI2cOpen(arg1 & 0x03);
                        }
                        else
                        {
                            Handler_.HandleI2cClose(arg1 & 0x03);
                        }
                        break;

                    case (int)IOIOProtocolCommands.I2C_RESULT:
                        arg1 = readByte();
                        arg2 = readByte();
                        if (arg2 != 0xFF)
                        {
                            data = readBytes(arg2);
                        }
                        else
                        {
                            data = new byte[0];
                        }
                        Handler_.HandleI2cResult(arg1 & 0x03, arg2, data);
                        break;

                    case (int)IOIOProtocolCommands.I2C_REPORT_TX_STATUS:
                        arg1 = readByte();
                        arg2 = readByte();
                        Handler_.HandleI2cReportTxStatus(arg1 & 0x03, (arg1 >> 2) | (arg2 << 6));
                        break;

                    case (int)IOIOProtocolCommands.CHECK_INTERFACE_RESPONSE:
                        // this is 0x63 on my sparkfun 016 running 503 sw
                        arg1 = readByte();
                        Handler_.HandleCheckInterfaceResponse((arg1 & 0x01) == 1);
                        break;

                    case (int)IOIOProtocolCommands.ICSP_REPORT_RX_STATUS:
                        arg1 = readByte();
                        arg2 = readByte();
                        Handler_.HandleIcspReportRxStatus(arg1 | (arg2 << 8));
                        break;

                    case (int)IOIOProtocolCommands.ICSP_RESULT:
                        size = 2;
                        data = readBytes(size);
                        Handler_.HandleIcspResult(size, data);
                        break;

                    case (int)IOIOProtocolCommands.ICSP_CONFIG:
                        arg1 = readByte();
                        if ((arg1 & 0x01) == 1)
                        {
                            Handler_.HandleIcspOpen();
                        }
                        else
                        {
                            Handler_.HandleIcspClose();
                        }
                        break;

                    case (int)IOIOProtocolCommands.INCAP_STATUS:
                        arg1 = readByte();
                        if ((arg1 & 0x80) != 0)
                        {
                            Handler_.HandleIncapOpen(arg1 & 0x0F);
                        }
                        else
                        {
                            Handler_.HandleIncapClose(arg1 & 0x0F);
                        }
                        break;

                    case (int)IOIOProtocolCommands.INCAP_REPORT:
                        arg1 = readByte();
                        size = arg1 >> 6;
                        if (size == 0)
                        {
                            size = 4;
                        }
                        data = readBytes(size);
                        Handler_.HandleIncapReport(arg1 & 0x0F, size, data);
                        break;

                    case (int)IOIOProtocolCommands.SOFT_CLOSE:
                        LOG.Debug("T:" + IncomingTask_.Id + " Received soft close.");
                        throw new IOException("Soft close");

                    case (int)IOIOProtocolCommands.CAPSENSE_REPORT:
                        arg1 = readByte();
                        arg2 = readByte();
                        Handler_.HandleCapSenseReport(arg1 & 0x3F, (arg1 >> 6) | (arg2 << 2));
                        break;

                    case (int)IOIOProtocolCommands.SET_CAPSENSE_SAMPLING:
                        arg1 = readByte();
                        Handler_.HandleSetCapSenseSampling(arg1 & 0x3F, (arg1 & 0x80) != 0);
                        break;

                    case (int)IOIOProtocolCommands.SEQUENCER_EVENT:
                        arg1 = readByte();
                        // OPEN and STOPPED events has an additional argument.
                        if (arg1 == 2 || arg1 == 4)
                        {
                            arg2 = readByte();
                        }
                        else
                        {
                            arg2 = 0;
                        }
                        try
                        {
                            // should be able to cast since enums are really int (gag)
                            Handler_.HandleSequencerEvent((SequencerEventState)arg1, arg2);
                        }
                        catch (Exception e)
                        {
                            throw new IOException("Unexpected event: " + arg1, e);
                        }
                        break;

                    case (int)IOIOProtocolCommands.SYNC:
                        Handler_.HandleSync();
                        break;

                    default:
                        throw new ProtocolError("Received unexpected command: 0x"
                                                + arg1.ToString("X"));
                    }
                }
            }
            catch (System.Threading.ThreadAbortException e)
            {
                LOG.Error("T:" + IncomingTask_.Id + " Probably aborted: (" + e.GetType() + ")" + e.Message);
                LOG.Error("T:" + IncomingTask_.Id + e.StackTrace);
            }
            catch (ObjectDisposedException e)
            {
                //// see this when steram is closed
                LOG.Error("T:" + IncomingTask_.Id + " Probably closed incoming Stream_: (" + e.GetType() + ")" + e.Message);
                LOG.Error("T:" + IncomingTask_.Id + e.StackTrace);
            }
            catch (IOException e)
            {
                LOG.Error("T:" + IncomingTask_.Id + " Probably aborted incoming: (" + e.GetType() + ")" + e.Message);
                LOG.Error("T:" + IncomingTask_.Id + e.StackTrace);
            }
            catch (Exception e)
            {
                LOG.Error("T:" + IncomingTask_.Id + " Unexpected Exception: (" + e.GetType() + ")" + e.Message);
                LOG.Error("T:" + IncomingTask_.Id + e.StackTrace);
            }
            finally
            {
                // we don't play swith Stream_ since we didn't create it
                Handler_.HandleConnectionLost();
                LOG.Info("T:" + IncomingTask_.Id + " Throwing thread cancel to stop incoming thread");
                CancelTokenSource_.Cancel();
                // debugger will always stop here in unit tests if test or app dynamically determines what Port_ ot use
                // just hit continue in the debugger when you get here on startup
                CancelTokenSource_.Token.ThrowIfCancellationRequested();
                Stream_            = null;
                this.IncomingTask_ = null;
            }
        }