コード例 #1
0
ファイル: ANT_Device.cs プロジェクト: Cycli/Cycli
        private void responsePollFunc()
        {
            ushort messageSize = 0;
            byte channelNum;
            bool isMsgForChannel;

            pollingOn = true;   //Set to false on shutdown to terminate the thread
            #if (ANTFS_DEBUGGING)
            ANT_Common.initDebugLogThread("Device" + USBDeviceNum + "_ANTReceive"); // We still need this for ANT-FS!  Will not be created if debug disabled
            #endif
            while (initializedUSB && pollingOn)    //check continuously; this thread is terminated on destruction of the class
            {
                // We only wait in the unmanged code for 100 ms because we want this thread to be responsive on our side.
                // It does mean that we are running through a lot more cycles than we need to
                messageSize = ANT_WaitForMessage(unmanagedANTFramerPtr, 100);

                if (messageSize == (ushort)0xFFFE)   //DSI_FRAMER_TIMEDOUT
                    continue;   //Expected, just keep looping

                ANTMessage newMessage = new ANTMessage();
                messageSize = ANT_GetMessage(unmanagedANTFramerPtr, ref newMessage);

                if (messageSize == (ushort)0xFFFF)  // DSI_FRAMER_ERROR - in current library could be from CRC error, Write error, Read error, or DeviceGone
                {
                    serialErrorCode error;
                    bool isCritical = false;

                    switch(newMessage.msgID)
                    {
                        case 0x02:  //DSI_FRAMER_ANT_ESERIAL
                            switch(newMessage.ucharBuf[0])
                            {
                                case 0x04:  //ESERIAL -> DSI_FRAMER_ANT_CRC_ERROR
                                    error = serialErrorCode.MessageLost_CrcError;
                                    break;
                                case 0x02:  //ESERIAL -> DSI_SERIAL_EWRITE
                                    error = serialErrorCode.SerialWriteError;
                                    break;
                                case 0x03:  //ESERIAL -> DSI_SERIAL_EREAD
                                    error = serialErrorCode.SerialReadError;
                                    isCritical = true;
                                    break;
                                case 0x01:  //ESERIAL -> DSI_SERIAL_DEVICE_GONE
                                    error = serialErrorCode.DeviceConnectionLost;
                                    isCritical = true;
                                    break;
                                default:
                                    error = serialErrorCode.Unknown;
                                    System.Diagnostics.Debug.Fail("Unknown serial failure, why isn't this known?");
                                    break;
                            }
                            break;
                        case 0x01:  //DSI_FRAMER_ANT_EQUEUE_OVERFLOW
                            error = serialErrorCode.MessageLost_QueueOverflow;
                            break;
                        case 0x03:  //DSI_FRAMER_ANT_EINVALID_SIZE
                            error = serialErrorCode.MessageLost_TooLarge;
                            break;
                        default:
                            error = serialErrorCode.Unknown;
                            System.Diagnostics.Debug.Fail("Unknown serial failure, why isn't this known?");
                            break;
                    }

                    if(isCritical)
                    {
                        //System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(x => shutdown())); //Clean up all resources on another thread to allow this one to close cleanly
                        pollingOn = false;  //Just stop polling, since we will never get new messages now. Allow the user to dispose of the device.
                    }

                    //If application has subscribed to the event we can inform them
                    if (serialError != null)
                        serialError(this, error, isCritical);
                    else   //Debug.Fail is a no-op in release mode, so we will only see this in debugging, in release mode we don't want to do anything intrusive (ie:message box, exception)
                        System.Diagnostics.Debug.Fail("Device Serial Communication Failure, HandleSerialError not handled by application");

                    if (isCritical)
                        break;  //If the device is dead, exit the polling loop
                    else
                        continue;
                }

                isMsgForChannel = false;
                channelNum = Byte.MaxValue;

                switch (newMessage.msgID)   //Check if we send to channel or protocol response func
                {
                    // Send on Channel event
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
                        if (newMessage.ucharBuf[1] == (byte)ANT_ReferenceLibrary.ANTMessageID.EVENT_0x01)
                            isMsgForChannel = true;
                        break;
                    // or any of the transmission events
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F:
            #if (!REFERENCE_DESIGN)
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.ADV_BURST_DATA_0x72:
            #endif
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_BROADCAST_DATA_0xC1:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_ACKNOWLEDGED_DATA_0xC2:
                    case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_BURST_DATA_0xC3:
                        isMsgForChannel = true;
                        break;
                }

                ANT_Response newResponse;

                //Now dispatch to appropriate event
                //The messages are buffered in the ant library so we just dispatch with current thread
                //then no matter how long the event call takes we still won't miss messages
                if (isMsgForChannel)
                {
                    channelNum = (byte)(newMessage.ucharBuf[0] & 0x1F); //Mask out what channel this is for. [We can eventually switch to use the c++ code to determine the channel, but we should do it all together with getMessage to avoid extra marshalling and copying and remove the processing in C# above]
                    if (antChannels != null && channelNum < antChannels.Length)
                    {
                        if (antChannels[channelNum] != null)
                            antChannels[channelNum].MessageReceived(newMessage, messageSize);
                    }
                    else
                    {
                        if (serialError != null)
                            serialError(this, serialErrorCode.MessageLost_InvalidChannel, false);
                    }
                }
                else
                {
                    newResponse = new ANT_Response(this, newMessage.ucharBuf[0], DateTime.Now, newMessage.msgID, newMessage.ucharBuf.Take(messageSize).ToArray());

                    if (deviceResponse != null) //Ensure events are assigned before we call the event
                        deviceResponse(newResponse);
                }

            }
        }
コード例 #2
0
ファイル: ANT_Device.cs プロジェクト: Cycli/Cycli
 private static extern int ANT_WriteMessage(IntPtr FramerPtr, ANTMessage pstANTMessage, UInt16 usMessageSize);
コード例 #3
0
ファイル: ANT_Device.cs プロジェクト: Cycli/Cycli
 private static extern byte ANT_GetChannelNumber(IntPtr FramerPtr, ref ANTMessage pstANTMessage);
コード例 #4
0
ファイル: ANT_Device.cs プロジェクト: Cycli/Cycli
 private static extern UInt16 ANT_GetMessage(IntPtr FramerPtr, ref ANTMessage ANT_MESSAGE_response);
コード例 #5
0
ファイル: ANT_Device.cs プロジェクト: Cycli/Cycli
        /// <summary>
        /// Writes a message to the device, this function allows sending manually formatted messages.
        /// </summary>
        /// <param name="msgID">msgID to write</param>
        /// <param name="msgData">data buffer to write</param>
        /// <returns>False if writing bytes to device fails</returns>
        public bool writeRawMessageToDevice(byte msgID, byte[] msgData)
        {
            if (!initializedUSB)
                throw new ObjectDisposedException("ANTDevice object has been disposed");

            //Create ANT_MESSAGE
            ANTMessage aMsg = new ANTMessage();
            aMsg.msgID = msgID;

            //We create an array of max size, because the struct sizing expects a constant size array
            int padNum = ANT_ReferenceLibrary.MAX_MESG_SIZE - msgData.Length;
            if(padNum < 0)
                throw new ANT_Exception("msgData max length is " + ANT_ReferenceLibrary.MAX_MESG_SIZE + " bytes");
            aMsg.ucharBuf = msgData.Concat(new byte[padNum]).ToArray();

            return ANT_WriteMessage(unmanagedANTFramerPtr, aMsg, (UInt16)msgData.Length) == 1;
        }