public void TestReceiveDump() { phy.SetPower(true); // page 0 Status status; PibValue value = new PibValue(); value.Int = 0; phy.SetRequest(PibAttribute.phyCurrentPage, value, out status); Assert(status == Status.Success); // channel 11 value.Int = 11; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); Assert(status == Status.Success); // sniff phy.DataIndication = phy_DataIndicationDump; phy.SetTrxStateRequest(State.RxOn, out status); Assert(status == Status.RxOn); for (; ; ) Thread.Sleep(5000); }
public void TestCommon() { // GetFrameHeaders { int mtu, head, tail; phy.GetMtuSize(out mtu, out head, out tail); Assert(mtu == 127); Assert(head == 2); Assert(tail == 0); } // Capabilities { bool res; phy.IsCapabilitySupported(Capabilities.AddressFilter, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.AutoAck, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.AutoFcs, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.PowerOff, out res); Assert(res == true); } phy.SetPower(true); // GetDeviceAddress { UInt64 mac; phy.GetDeviceAddress(out mac); String s = String.Empty; for (int i = 0; i < 8; i++) { if (i > 0) s += ":"; s += HexConverter.ConvertUintToHex((UInt32)((mac >> i * 8) & 0xFF), 2); } Debug.Print(s); } // GetRequest { Status status; PibValue value; // constants phy.GetRequest(PibAttribute.phyChannelsSupported, out status, out value); Assert(status == Status.Success); int[] res = value.IntArray; Assert(res != null); Assert(res.Length == 1); Assert((res[0] & 0xF8000000) == 0); // page 0 for (int i = 0; i <= 27; i++) { bool val = (res[0] & (1 << i)) != 0; bool expected = (i >= 11 && i <= 26); Assert(val == expected); } phy.GetRequest(PibAttribute.phyCCAMode, out status, out value); Assert(status == Status.Success); Assert(value.Int == 3); phy.GetRequest(PibAttribute.phyCurrentPage, out status, out value); Assert(status == Status.Success); Assert(value.Int == 0); phy.GetRequest(PibAttribute.phyMaxFrameDuration, out status, out value); Assert(status == Status.Success); Assert(value.Int == 1064); phy.GetRequest(PibAttribute.phySHRDuration, out status, out value); Assert(status == Status.Success); Assert(value.Int == 40); phy.GetRequest(PibAttribute.phySymbolsPerOctet, out status, out value); Assert(status == Status.Success); Assert(value.Float == 8); // defaults phy.GetRequest(PibAttribute.phyCurrentChannel, out status, out value); Assert(status == Status.Success); Assert(value.Int == 11); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); Assert(value.Int == -1); } // SetRequest { // constants Status status; PibValue value = new PibValue(); int[] res = new int[1]; res[0] = 256; value.IntArray = res; phy.SetRequest(PibAttribute.phyChannelsSupported, value, out status); Assert(status == Status.ReadOnly); value.Int = 0; phy.SetRequest(PibAttribute.phyCCAMode, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phyMaxFrameDuration, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phySHRDuration, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phySymbolsPerOctet, value, out status); Assert(status == Status.ReadOnly); // page phy.SetRequest(PibAttribute.phyCurrentPage, value, out status); Assert(status == Status.Success); value.Int = 1; phy.SetRequest(PibAttribute.phyCurrentPage, value, out status); Assert(status == Status.InvalidParam); // channel for (int i = 0; i < 27; i++) { value.Int = i; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); if (i >= 11 && i <= 26) { Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyCurrentChannel, out status, out value); Assert(status == Status.Success); Assert(value.Int == i); } else { Assert(status == Status.InvalidParam); } } // power value.Int = -100; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.InvalidParam); value.Int = -32; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); value.Int = 1; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); Assert(value.Int == 0); // max CC tx power value.Int = 64; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.InvalidParam); } phy.SetPower(false); }
public void TestSend(bool bSendData) { phy.SetPower(true); phy.SetAutoFCS(true); int mtu, head, tail; phy.GetMtuSize(out mtu, out head, out tail); PibValue value = new PibValue(); Status status; value.Int = 11; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); Assert(status == Status.Success); value.Int = 0; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.Success); if (bSendData) { // Sends data continously. Dummy processing. phy.DataIndication = phy_DataIndicationDummy; } else { // Does not send data. During receive pings data back. phy.DataIndication = phy_DataIndicationAqc; } phy.SetTrxStateRequest(State.RxOn, out status); byte[] packetData = new byte[100]; DateTime prevTime = DateTime.Now; byte[] b = new byte[128]; Thread.Sleep(10); if (!bSendData) { return; } for (int i = 0; ; ++i) { // build custom frame m_frame.ReserveHeader(head); int cInd = -1; ushort u = (ushort)(1 << 0) | // m_frame type: data (0 << 3) | // security: none (0 << 4) | // m_frame pending: none (1 << 5) | // ack request: true (1 << 6) | // pan id compression: true (2 << 10) | // dst addr: short addr (2 << 14); // src addr: short addr b[++cInd] = (byte)(u & 0xFF); b[++cInd] = (byte)(u >> 8); // Append sequence number. b[++cInd] = (byte)i; // seq no u = 1; // pan id b[++cInd] = (byte)(u & 0xFF); b[++cInd] = (byte)(u >> 8); u = 2; b[++cInd] = (byte)(u & 0xFF); b[++cInd] = (byte)(u >> 8); u = 3; b[++cInd] = (byte)(u & 0xFF); b[++cInd] = (byte)(u >> 8); b[++cInd] = 0xDE; b[++cInd] = 0xAD; b[++cInd] = 0xBE; b[++cInd] = 0xEF; // dead beef m_frame.AppendToBack(b, 0, cInd + 1 + 100); // payload do { phy.DataRequest(m_frame, out status); } while (status != Status.Success); DateTime curTime = DateTime.Now; Debug.Print("Frame " + (byte)i + " is sent at " + curTime.Second + ":" + curTime.Millisecond); Thread.Sleep(2000); } }
public void TestReceive() { phy.SetPower(true); phy.DataIndication = phy_DataIndicationDummy; // EDRequest { Debug.Print("EDRequest"); Status status; Byte energyLevel; phy.SetTrxStateRequest(State.TRxOff, out status); Assert(status == Status.TRxOff); phy.EDRequest(out status, out energyLevel); Assert(status == Status.TRxOff); phy.SetTrxStateRequest(State.RxOn, out status); Assert(status == Status.RxOn); for (int i = 0; i < 5; i++) { leds.color = Leds.Color.Blue; for (int channel = 11; channel <= 26; channel++) { PibValue value = new PibValue(); value.Int = channel; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); Assert(status == Status.Success); phy.EDRequest(out status, out energyLevel); if (status == Status.Success) { String s = String.Empty; s += "ED: " + energyLevel + " on " + channel; Debug.Print(s); } } leds.color = Leds.Color.Off; System.Threading.Thread.Sleep(100); } } // CCARequest { Debug.Print("CCA"); PibValue value = new PibValue(); value.Int = 11; Status status; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); Assert(status == Status.Success); phy.SetTrxStateRequest(State.RxOn, out status); Assert(status == Status.RxOn); DateTime start = DateTime.Now; TimeSpan duration = new TimeSpan(0, 0, 5); while (DateTime.Now - start < duration) { phy.CCARequest(out status); if (status == Status.Busy) leds.color = Leds.Color.Yellow; else leds.color = Leds.Color.Off; } leds.color = Leds.Color.Off; } // DataIndication phy.SetAutoFCS(true); phy.SetAddressFilter(true, 2, 1, false); // ok, no recv for other short addr/pan id phy.SetAutoAck(true); phy.DataIndication = phy_DataIndicationFlash; { Status status; phy.SetTrxStateRequest(State.RxOn, out status); Assert(status == Status.RxOn); Thread.Sleep(5000); } }
private void SetRequest(TaskSetRequest task) { if (task == null) return; MacEnum status = MacEnum.Success; lock (_state) { switch (task.attribute) { case PibAttribute.phyCurrentChannel: case PibAttribute.phyChannelsSupported: case PibAttribute.phyTransmitPower: case PibAttribute.phyCCAMode: case PibAttribute.phyCurrentPage: case PibAttribute.phyMaxFrameDuration: case PibAttribute.phySHRDuration: case PibAttribute.phySymbolsPerOctet: { Phy.Status statusPhy; Phy.PibValue value = new Phy.PibValue(); switch (task.value.Type) { case PibValue.ValueType.Int: value.Int = task.value.Int; break; case PibValue.ValueType.IntArray: value.IntArray = task.value.IntArray; break; case PibValue.ValueType.Float: value.Float = task.value.Float; break; } _phy.SetRequest((Phy.PibAttribute)task.attribute, value, out statusPhy); if (statusPhy != Phy.Status.Success) { if (statusPhy == Phy.Status.InvalidParam) status = MacEnum.InvalidParameter; else status = MacEnum.UnsupportedAttribute; } break; } case PibAttribute.macBeaconPayload: if (task.value.Type == PibValue.ValueType.Frame) { Frame.Release(ref _state.macBeaconPayload); _state.macBeaconPayload = task.value.Frame; } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macPanId: if (task.value.Type == PibValue.ValueType.Int) { _state.macPanId = (UInt16)task.value.Int; } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macPromiscuousMode: if (task.value.Type == PibValue.ValueType.Bool) { _state.macPromiscousMode = task.value.Bool; } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macShortAddress: if (task.value.Type == PibValue.ValueType.Int) { _state.macShortAddr = (UInt16)task.value.Int; } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macBeaconOrder: if (task.value.Type == PibValue.ValueType.Int) { _state.macBeaconOrder = FixParameter((byte)task.value.Int, 0, 15); } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macSuperframeOrder: if (task.value.Type == PibValue.ValueType.Int) { _state.macSuperframeOrder = FixParameter((byte)task.value.Int, 0, 15); } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macMinBE: if (task.value.Type == PibValue.ValueType.Int) { _state.macMinBE = FixParameter((byte)task.value.Int, 0, _state.macMaxBE); } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macMaxBE: if (task.value.Type == PibValue.ValueType.Int) { _state.macMaxBE = FixParameter((byte)task.value.Int, 3, 8); if (_state.macMinBE > _state.macMaxBE) _state.macMinBE = _state.macMaxBE; } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macMaxCSMABackoffs: if (task.value.Type == PibValue.ValueType.Int) { _state.macMaxCSMABackoffs = FixParameter((byte)task.value.Int, 0, 5); } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macMaxFrameRetries: if (task.value.Type == PibValue.ValueType.Int) { _state.macMaxFrameRetries = FixParameter((byte)task.value.Int, 0, 7); } else { status = MacEnum.InvalidParameter; } break; case PibAttribute.macAckWaitDuration: case PibAttribute.macAssociatedPANCoord: case PibAttribute.macAssociationPermit: case PibAttribute.macAutoRequest: case PibAttribute.macBattLifeExt: case PibAttribute.macBattLifeExtPeriods: case PibAttribute.macBeaconTxTime: case PibAttribute.macBSN: case PibAttribute.macCoordExtendedAddress: case PibAttribute.macCoordShortAddress: case PibAttribute.macDSN: case PibAttribute.macGTSPermit: case PibAttribute.macMaxFrameTotalWaitTime: case PibAttribute.macResponseWaitTime: case PibAttribute.macRxOnWhenIdle: case PibAttribute.macSecurityEnabled: case PibAttribute.macSyncSymbolOffset: case PibAttribute.macTimestampSupported: case PibAttribute.macTransactionPersistenceTime: status = MacEnum.UnsupportedAttribute; Trace.Print("Mac: SetRequest: unsupported attribute"); break; } } if (task.handler != null) { task.handler.Invoke(this, status, task.attribute, task.index); } }
private void StartRequest(TaskStartRequest task) { if (task == null) return; MacEnum status = MacEnum.Success; lock (_state) { // test short addr if (status == MacEnum.Success) { if (_state.macShortAddr == State.cReservedShortAddr) { status = MacEnum.NoShortAddress; } } // test beacon if (status == MacEnum.Success) { // need to check if beacon does not exceed size when applying given security. // as security is not yet implemented, nothing to do here //MacEnum.FrameTooLong } // set page if (status == MacEnum.Success) { if (_state.phyChannelPage != task.channelPage) { int channelPage = task.channelPage; Phy.Status statusPhy; Phy.PibValue value = new Phy.PibValue(); value.Int = channelPage; _phy.SetRequest(Phy.PibAttribute.phyCurrentPage, value, out statusPhy); if (statusPhy == Phy.Status.Success) { _state.phyChannelPage = task.channelPage; } else { status = MacEnum.InvalidParameter; } } } // set channel if (status == MacEnum.Success) { if (_state.phyChannelNumber != task.logicalChannel) { Phy.Status statusPhy; Phy.PibValue value = new Phy.PibValue(); value.Int = task.logicalChannel; _phy.SetRequest(Phy.PibAttribute.phyCurrentChannel, value, out statusPhy); if (statusPhy == Phy.Status.Success) { _state.phyChannelNumber = task.logicalChannel; } else { status = MacEnum.InvalidParameter; } } } // FIXME: ignoring various parameters for now //UInt16 startTime; //byte beaconOrder; //byte superframeOrder; //bool batteryLifeExtension; //bool coordRealignment; //SecurityOptions coordRealignSecutiryOptions; //SecurityOptions beaconSecurityOptions; if (status == MacEnum.Success) { _state.macPanId = task.panId; _state.panCoordinator = task.panCoordinator; _state.autoBeacon = true; _sendReceive.Start(); } } if (task.handler != null) task.handler.Invoke(this, status); }
private void ScanRequest(TaskScanRequest task) { if (task == null) return; if (task.handler == null) return; UInt16 oldPanId; lock (_state) { // recv thread is holding lock while processing frames. this ensures consistency _state.scanning = true; oldPanId = _state.macPanId; _state.macPanId = State.cBroadcastPanId; } bool wasRunning = _sendReceive.Running; if (!wasRunning) _sendReceive.Start(); // calculate scan duration UInt32 durationSymbols = task.scanDuration; if (durationSymbols > 14) durationSymbols = 14; durationSymbols = (UInt32)(State.aBaseSuperframeDuration * ((1 << (int)durationSymbols) + 1)); // result UInt32 unscannedChannels = 0; // bitmap byte[] energyDetectList = null; PanDescriptor[] panDescriptorList = null; // set page Phy.Status status; Phy.PibValue pibValue = new Phy.PibValue(); pibValue.Int = task.channelPage; _phy.SetRequest(Phy.PibAttribute.phyCurrentPage, pibValue, out status); if (status != Phy.Status.Success) { unscannedChannels = task.scanChannels; } else { _state.phyChannelPage = task.channelPage; // energyDetectList int channelCount = 0; if (task.scanType == ScanType.ED) { for (int channel = 0; channel < 27; channel++) { if (((1 << channel) & task.scanChannels) != 0) { channelCount++; } } energyDetectList = new byte[channelCount]; channelCount = 0; } // Note: there can be a race between switching the channels here and getting the current channel when // receiving beacons in MacReceive. This is solved through thread priorities: recv thread has higher // priority and should not be blocked from this thread. There is still a small chance that we switch // channel and recv assigns the new (wrong) channel, but this is by design and cannot be changed. // iterate through all channels for (int channel = 0; channel < 27; channel++) { if (((1 << channel) & task.scanChannels) != 0) { // set channel pibValue.Int = channel; _phy.SetRequest(Phy.PibAttribute.phyCurrentChannel, pibValue, out status); if (status != Phy.Status.Success) { unscannedChannels |= (UInt32)(1 << channel); channelCount++; } else { _state.phyChannelNumber = (Byte)channel; // max value of durationSymb is 2^24, correct would be: dur*1000/rate, however this exceeds int range // as symbolrate is multiple of 100, this works: int durationMS = (int)(durationSymbols * 10) / (_state.phySymbolrate / 100); // symbolrate is non-zero // perform the actual channel request switch (task.scanType) { case ScanType.ED: { // Continuously read ED values in software for given amount of time. #if MICROFRAMEWORK ThreadPriority oldPriority = Thread.CurrentThread.Priority; Thread.CurrentThread.Priority = ThreadPriority.Highest; // RT thread #endif Byte result = 0; bool resultValid = false; DateTime dtStart = System.DateTime.Now; for (; ; ) { Byte b; _phy.EDRequest(out status, out b); if (status == Phy.Status.Success) { resultValid = true; if (b > result) result = b; } //Thread.Sleep(1); DateTime dtNow = System.DateTime.Now; TimeSpan ts = dtNow - dtStart; int elapsedMS = ts.Milliseconds + 1000 * (ts.Seconds + 60 * ts.Minutes); if (elapsedMS >= durationMS) break; } #if MICROFRAMEWORK Thread.CurrentThread.Priority = oldPriority; #endif if (resultValid) { energyDetectList[channelCount] = result; } else { unscannedChannels |= (UInt32)(1 << channel); } channelCount++; Thread.Sleep(0); // reschedule break; } case ScanType.ActiveScan: case ScanType.PassiveScan: { // clear any old beacon lock (_scannedBeacons) { _scannedBeacons.Clear(); } // send beacon request if (task.scanType == ScanType.ActiveScan) { Header hdr = new Header(); Command.BeaconRequest cmd = new Command.BeaconRequest(); hdr.fcs.Type = Microsoft.SPOT.Wireless.IEEE_802_15_4.Mac.Frames.Type.Cmd; hdr.fcs.DstAddrMode = AddressingMode.Short; hdr.dstAddrShort = State.cBroadcastShortAddr; hdr.dstPanId = State.cBroadcastPanId; hdr.fcs.SrcAddrMode = AddressingMode.None; hdr.seqNo = _state.macDSN++; Frame frame = Encode(hdr, cmd); if (frame != null) _sendReceive.SendFrame(ref frame, false, hdr.seqNo); Frame.Release(ref frame); } // wait Thread.Sleep(durationMS); // create result list lock (_scannedBeacons) { if (_scannedBeacons.Count > 0) { int cntOld = 0; int cntNew = _scannedBeacons.Count; if (panDescriptorList == null) { panDescriptorList = new PanDescriptor[cntNew]; } else { cntOld = panDescriptorList.Length; PanDescriptor[] tmp = new PanDescriptor[cntOld + cntNew]; for (int i = 0; i < cntOld; i++) tmp[i] = panDescriptorList[i]; panDescriptorList = tmp; } for (int i = 0; i < cntNew; i++) panDescriptorList[i + cntOld] = (PanDescriptor)_scannedBeacons[i]; _scannedBeacons.Clear(); } } break; } case ScanType.OrphanScan: // FIXME: not implemented Trace.Print("Mac: ScanRequest: OrphanScan not implemented"); unscannedChannels |= (UInt32)(1 << channel); break; } } } } } if (!wasRunning) _sendReceive.Stop(); lock (_state) { _state.scanning = false; _state.macPanId = oldPanId; } task.handler.Invoke(this, MacEnum.Success, task.scanType, task.channelPage, unscannedChannels, energyDetectList, panDescriptorList); }
/// <summary> /// (6.2.2.9-10) The PLME-SET.request primitive attempts to set the indicated PHY PIB attribute to the given value. /// </summary> /// <param name="attribute">The identifier of the PIB attribute to set.</param> /// <param name="attributeValue">The value of the indicated PIB attribute to set.</param> /// <param name="status">The status of the attempt to set the requested PIB attribute.</param> public void SetRequest( PibAttribute attribute, PibValue attributeValue, out Status status) { switch (attribute) { case PibAttribute.phyCurrentChannel: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value < HALCC2420.MinChannel || value > HALCC2420.MaxChannel) { status = Status.InvalidParam; } else { Channel = (byte)value; status = Status.Success; } } break; } case PibAttribute.phyTransmitPower: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value < -32 || value > 31) // dBm { status = Status.InvalidParam; } else { Power = value; status = Status.Success; } } break; } case PibAttribute.phyCurrentPage: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value == 0) status = Status.Success; else status = Status.InvalidParam; } break; } case PibAttribute.phyChannelsSupported: case PibAttribute.phyCCAMode: case PibAttribute.phyMaxFrameDuration: case PibAttribute.phySHRDuration: case PibAttribute.phySymbolsPerOctet: status = Status.ReadOnly; break; default: status = Status.InvalidParam; break; } }
/// <summary> /// (6.2.2.5-6) The PLME-GET.request primitive requests information about a given PHY PIB attribute. /// </summary> /// <param name="attribute">The identifier of the PHY PIB attribute to get.</param> /// <param name="status">The result of the request for PHY PIB attribute information.</param> /// <param name="attributeValue">The value of the indicated PHY PIB attribute that was requested. This /// parameter has zero length when the status parameter is set to UNSUPPORTED_ATTRIBUTE.</param> public void GetRequest( PibAttribute attribute, out Status status, out PibValue attributeValue) { attributeValue = new PibValue(); switch (attribute) { case PibAttribute.phyCurrentChannel: status = Status.Success; attributeValue.Int = Channel; break; case PibAttribute.phyChannelsSupported: { int res = 0; for (int i = HALCC2420.MinChannel; i <= HALCC2420.MaxChannel; i++) res |= (1 << i); // CC2420 only supports channel page 0 int[] channels = new int[1]; channels[0] = res; status = Status.Success; attributeValue.IntArray = channels; break; } case PibAttribute.phyTransmitPower: status = Status.Success; attributeValue.Int = Power; break; case PibAttribute.phyCCAMode: status = Status.Success; attributeValue.Int = 3; // hard-coded in hal, could be changed break; case PibAttribute.phyCurrentPage: status = Status.Success; attributeValue.Int = 0; break; case PibAttribute.phyMaxFrameDuration: // see 6.4.2 and below status = Status.Success; attributeValue.Int = 1064; break; case PibAttribute.phySHRDuration: // SHR is 4+1 byte, BPSK (5*8) status = Status.Success; attributeValue.Int = 40; break; case PibAttribute.phySymbolsPerOctet: status = Status.Success; attributeValue.Float = 8; // BPSK only break; default: status = Status.UnsupportedAttr; break; } }
/// <summary> /// (6.2.2.5-6) The PLME-GET.request primitive requests information about a given PHY PIB attribute. /// </summary> /// <param name="attribute">The identifier of the PHY PIB attribute to get.</param> /// <param name="status">The result of the request for PHY PIB attribute information.</param> /// <param name="attributeValue">The value of the indicated PHY PIB attribute that was requested. This /// parameter has zero length when the status parameter is set to UNSUPPORTED_ATTRIBUTE.</param> public void GetRequest( PibAttribute attribute, out Status status, out PibValue attributeValue) { attributeValue = new PibValue(); switch (attribute) { case PibAttribute.phyCurrentChannel: status = Status.Success; attributeValue.Int = Channel; break; case PibAttribute.phyChannelsSupported: { int res = 0; for (int i = HALCC2420.MinChannel; i <= HALCC2420.MaxChannel; i++) { res |= (1 << i); } // CC2420 only supports channel page 0 int[] channels = new int[1]; channels[0] = res; status = Status.Success; attributeValue.IntArray = channels; break; } case PibAttribute.phyTransmitPower: status = Status.Success; attributeValue.Int = Power; break; case PibAttribute.phyCCAMode: status = Status.Success; attributeValue.Int = 3; // hard-coded in hal, could be changed break; case PibAttribute.phyCurrentPage: status = Status.Success; attributeValue.Int = 0; break; case PibAttribute.phyMaxFrameDuration: // see 6.4.2 and below status = Status.Success; attributeValue.Int = 1064; break; case PibAttribute.phySHRDuration: // SHR is 4+1 byte, BPSK (5*8) status = Status.Success; attributeValue.Int = 40; break; case PibAttribute.phySymbolsPerOctet: status = Status.Success; attributeValue.Float = 8; // BPSK only break; default: status = Status.UnsupportedAttr; break; } }
/// <summary> /// (6.2.2.9-10) The PLME-SET.request primitive attempts to set the indicated PHY PIB attribute to the given value. /// </summary> /// <param name="attribute">The identifier of the PIB attribute to set.</param> /// <param name="attributeValue">The value of the indicated PIB attribute to set.</param> /// <param name="status">The status of the attempt to set the requested PIB attribute.</param> public void SetRequest( PibAttribute attribute, PibValue attributeValue, out Status status) { switch (attribute) { case PibAttribute.phyCurrentChannel: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value < HALCC2420.MinChannel || value > HALCC2420.MaxChannel) { status = Status.InvalidParam; } else { Channel = (byte)value; status = Status.Success; } } break; } case PibAttribute.phyTransmitPower: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value < -32 || value > 31) // dBm { status = Status.InvalidParam; } else { Power = value; status = Status.Success; } } break; } case PibAttribute.phyCurrentPage: { if (attributeValue.Type != PibValue.ValueType.Int) { status = Status.InvalidParam; } else { int value = attributeValue.Int; if (value == 0) { status = Status.Success; } else { status = Status.InvalidParam; } } break; } case PibAttribute.phyChannelsSupported: case PibAttribute.phyCCAMode: case PibAttribute.phyMaxFrameDuration: case PibAttribute.phySHRDuration: case PibAttribute.phySymbolsPerOctet: status = Status.ReadOnly; break; default: status = Status.InvalidParam; break; } }