Example #1
0
        public static Frame CreateACK(byte sequenceNumber, bool pending)
        {
            var result = new Frame();
            result.Length = 5;
            result.Type = FrameType.ACK;
            result.FramePending = pending;
            result.DataSequenceNumber = sequenceNumber;
            result.Encode();

            return result;
        }
Example #2
0
        private bool ShouldWeAcceptThisFrame(Frame frame)
        {
            // (1) check if length is ok
            // (2) check reserved FCF bits
            // for now we assume it is fine - let's be optimistic

            // (3) check FCF version
            if(frame.FrameVersion > maxFrameVersion.Value)
            {
                this.Log(LogLevel.Noisy, "Wrong frame version.");
                return false;
            }

            // (4) check source/destination addressing mode
            if(frame.SourceAddressingMode == AddressingMode.Reserved || frame.DestinationAddressingMode == AddressingMode.Reserved)
            {
                this.Log(LogLevel.Noisy, "Wrong addressing mode.");
                return false;
            }

            // (5) check destination address
            if(frame.DestinationAddressingMode != AddressingMode.None)
            {
                // (5.1) check destination PAN
                if(frame.AddressInformation.DestinationPan != BroadcastPanIdentifier && frame.AddressInformation.DestinationPan != GetPanId())
                {
                    this.Log(LogLevel.Noisy, "Wrong destination PAN.");
                    return false;
                }
                // (5.2) check destination short address
                if(frame.DestinationAddressingMode == AddressingMode.ShortAddress)
                {
                    if(!frame.AddressInformation.DestinationAddress.IsShortBroadcast && !frame.AddressInformation.DestinationAddress.Equals(shortAddress))
                    {
                        this.Log(LogLevel.Noisy, "Wrong destination short address.");
                        return false;
                    }
                }
                // (5.3) check destination extended address
                else if(frame.DestinationAddressingMode == AddressingMode.ExtendedAddress)
                {
                    if(!frame.AddressInformation.DestinationAddress.Equals(extendedAddress))
                    {
                        this.Log(LogLevel.Noisy, "Wrong destination extended address (i'm {0}, but the message is directed to {1}.", extendedAddress.GetValue(), frame.AddressInformation.DestinationAddress.GetValue());
                        return false;
                    }
                }
            }

            // (6) check frame type
            switch(frame.Type)
            {
                case FrameType.Beacon:
                    if(!acceptBeaconFrames.Value
                        || frame.Length < 9
                        || frame.DestinationAddressingMode != AddressingMode.None
                        || (frame.SourceAddressingMode != AddressingMode.ShortAddress && frame.SourceAddressingMode != AddressingMode.ExtendedAddress)
                        || (frame.AddressInformation.SourcePan != BroadcastPanIdentifier && frame.AddressInformation.SourcePan != GetPanId()))
                    {
                        this.Log(LogLevel.Noisy, "Wrong beacon frame.");
                        return false;
                    }
                    break;
                case FrameType.Data:
                    if(!acceptDataFrames.Value
                        || frame.Length < 9
                        || (frame.DestinationAddressingMode == AddressingMode.None
                            && (!isPanCoordinator.Value || frame.AddressInformation.SourcePan != GetPanId())))
                    {
                        this.Log(LogLevel.Noisy, "Wrong data frame.");
                        return false;
                    }
                    break;
                case FrameType.ACK:
                    if(!acceptAckFrames.Value || frame.Length != 5)
                    {
                        this.Log(LogLevel.Noisy, "Wrong ACK frame.");
                        return false;
                    }
                    break;
                case FrameType.MACControl:
                    if(!acceptMacCmdFrames.Value
                        || frame.Length < 9
                        || (frame.DestinationAddressingMode == AddressingMode.None
                            && (!isPanCoordinator.Value || frame.AddressInformation.SourcePan != GetPanId())))
                    {
                        this.Log(LogLevel.Noisy, "Wrong MAC control frame.");
                        return false;
                    }
                    break;
                default:
                    return false;
            }

            return true;
        }
Example #3
0
        private void SendData()
        {
            if(txQueue.Count == 0)
            {
                this.Log(LogLevel.Warning, "Attempted to transmit an empty frame.");
                return;
            }

            irqHandler.RequestInterrupt(InterruptSource.StartOfFrameDelimiter);

            var crc = Frame.CalculateCRC(txQueue.Skip(1));
            var frame = new Frame(txQueue.Concat(crc).ToArray());

            this.DebugLog("Sending frame {0}.", frame.Bytes.Select(x => "0x{0:X}".FormatWith(x)).Stringify());
            var frameSent = FrameSent;
            if(frameSent != null)
            {
                frameSent(this, frame.Bytes);
            }

            irqHandler.RequestInterrupt(InterruptSource.TxDone);
        }
Example #4
0
        public void ReceiveFrame(byte[] bytes)
        {
            irqHandler.RequestInterrupt(InterruptSource.StartOfFrameDelimiter);

            Frame ackFrame = null;
            var frame = new Frame(bytes);

            var crcOK = frame.CheckCRC();
            if(autoCrc.Value && !crcOK)
            {
                this.Log(LogLevel.Warning, "Received frame with wrong CRC");
            }

            if(frameFilterEnabled.Value)
            {
                if(!ShouldWeAcceptThisFrame(frame))
                {
                    this.DebugLog("Not accepting a frame");
                    return;
                }

                irqHandler.RequestInterrupt(InterruptSource.FrameAccepted);
            }

            lock(rxLock)
            {
                var autoPendingBit = false;
                var index = NoSourceIndex;
                if(sourceAddressMatchingEnabled.Value && crcOK)
                {
                    switch(frame.SourceAddressingMode)
                    {
                        case AddressingMode.ShortAddress:
                            for(var i = 0u; i < srcShortEnabled.Length; i++)
                            {
                                if(!srcShortEnabled[i])
                                {
                                    continue;
                                }
                                if(frame.AddressInformation.SourcePan == GetShortPanIdFromRamTable(i)
                                   && frame.AddressInformation.SourceAddress.GetValue() == GetShortSourceAddressFromRamTable(i))
                                {
                                    matchedSourceAddresses[i] = true;
                                    autoPendingBit |= srcShortPendEnabled[i];
                                    if(index == NoSourceIndex)
                                    {
                                        index = i;
                                    }
                                }
                            }
                            break;
                        case AddressingMode.ExtendedAddress:
                            for(var i = 0u; i < srcExtendedEnabled.Length; i++)
                            {
                                if(!srcExtendedEnabled[i])
                                {
                                    continue;
                                }
                                if(frame.AddressInformation.SourceAddress.GetValue() == GetExtendedSourceAddressFromRamTable(i))
                                {
                                    matchedSourceAddresses[2 * i] = true;
                                    matchedSourceAddresses[2 * i + 1] = true;
                                    autoPendingBit |= srcExtendedPendEnabled[i];
                                    if(index == NoSourceIndex)
                                    {
                                        index = i | 0x20;
                                    }
                                }
                            }
                            break;
                    }

                    matchedSourceIndexField.Value = index;

                    autoPendingBit &= autoPendEnabled.Value
                                        && frameFilterEnabled.Value
                                        && (!pendDataRequestOnly.Value
                                            || (frame.Type == FrameType.MACControl
                                                && frame.Payload.Count > 0
                                                && frame.Payload[0] == 0x4));

                    BitHelper.SetBit(ref index, 6, autoPendingBit);
                    if(index != NoSourceIndex)
                    {
                        irqHandler.RequestInterrupt(InterruptSource.SrcMatchFound);
                    }
                    irqHandler.RequestInterrupt(InterruptSource.SrcMatchDone);
                }

                if(autoCrc.Value)
                {
                    var rssi = 70; // why 70?
                    var secondByte = crcOK ? (1u << 7) : 0;
                    if(appendDataMode.Value)
                    {
                        secondByte |= index & 0x7F;
                    }
                    else {
                        secondByte |= 100; // correlation value 100 means near maximum quality
                    }
                    frame.Bytes[frame.Bytes.Length - 2] = (byte)rssi;
                    frame.Bytes[frame.Bytes.Length - 1] = (byte)secondByte;
                }

                rxQueue.Enqueue(frame);
                irqHandler.RequestInterrupt(InterruptSource.FifoP);
                if(crcOK && autoAck.Value
                    && frame.AcknowledgeRequest
                    && frame.Type != FrameType.Beacon
                    && frame.Type != FrameType.ACK)
                {
                    ackFrame = Frame.CreateACK(frame.DataSequenceNumber, pendingOr.Value | autoPendingBit);
                }
            }

            var frameSent = FrameSent;
            if(frameSent != null && ackFrame != null)
            {
                frameSent(this, ackFrame.Bytes);
                irqHandler.RequestInterrupt(InterruptSource.TxAckDone);
            }

            irqHandler.RequestInterrupt(InterruptSource.RxPktDone);
        }