[Tinyos-2-commits] CVS: tinyos-2.x/tos/lib/mac/tkn154 AssociateP.nc, NONE, 1.1 BackupP.nc, NONE, 1.1 BeaconSynchronizeP.nc, NONE, 1.1 BeaconTransmitP.nc, NONE, 1.1 CapP.nc, NONE, 1.1 CapQueueP.nc, NONE, 1.1 CoordBroadcastP.nc, NONE, 1.1 CoordRealignmentP.nc, NONE, 1.1 DataP.nc, NONE, 1.1 FrameDispatchImplP.nc, NONE, 1.1 FrameDispatchP.nc, NONE, 1.1 IndirectTxP.nc, NONE, 1.1 PibP.nc, NONE, 1.1 PollP.nc, NONE, 1.1 RadioClientC.nc, NONE, 1.1 README.txt, NONE, 1.1 RxEnableP.nc, NONE, 1.1 ScanP.nc, NONE, 1.1 SimpleRoundRobinTransferArbiterC.nc, NONE, 1.1 SimpleTransferArbiterP.nc, NONE, 1.1 TKN154_DEBUG.h, NONE, 1.1 TKN154.h, NONE, 1.1 TKN154_MAC.h, NONE, 1.1 TKN154_PIB.h, NONE, 1.1 TKN154P.nc, NONE, 1.1 TransferClientP.nc, NONE, 1.1
Jan-Hinrich Hauer
janhauer at users.sourceforge.net
Mon Jun 16 11:00:32 PDT 2008
Update of /cvsroot/tinyos/tinyos-2.x/tos/lib/mac/tkn154
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv30549/tos/lib/mac/tkn154
Added Files:
AssociateP.nc BackupP.nc BeaconSynchronizeP.nc
BeaconTransmitP.nc CapP.nc CapQueueP.nc CoordBroadcastP.nc
CoordRealignmentP.nc DataP.nc FrameDispatchImplP.nc
FrameDispatchP.nc IndirectTxP.nc PibP.nc PollP.nc
RadioClientC.nc README.txt RxEnableP.nc ScanP.nc
SimpleRoundRobinTransferArbiterC.nc SimpleTransferArbiterP.nc
TKN154_DEBUG.h TKN154.h TKN154_MAC.h TKN154_PIB.h TKN154P.nc
TransferClientP.nc
Log Message:
Initial version of TKN15.4, a platform-independent IEEE 802.15.4-2006 MAC implementation (see tinyos-2.x/tos/lib/mac/tkn154/README.txt)
--- NEW FILE: AssociateP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:22 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
module AssociateP
{
provides
{
interface Init;
interface MLME_ASSOCIATE;
interface MLME_DISASSOCIATE;
interface MLME_COMM_STATUS;
}
uses
{
interface FrameRx as AssociationRequestRx;
interface FrameTx as AssociationRequestTx;
interface FrameExtracted as AssociationResponseExtracted;
interface FrameTx as AssociationResponseTx;
interface FrameTx as DisassociationIndirectTx;
interface FrameTx as DisassociationDirectTx;
interface FrameTx as DisassociationToCoord;
interface FrameRx as DisassociationDirectRxFromCoord;
interface FrameExtracted as DisassociationExtractedFromCoord;
interface FrameRx as DisassociationRxFromDevice;
interface DataRequest;
interface Timer<TSymbolIEEE802154> as ResponseTimeout;
interface Get<bool> as IsTrackingBeacons;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface Pool<ieee154_txcontrol_t> as TxControlPool;
interface MLME_GET;
interface MLME_SET;
interface FrameUtility;
interface IEEE154Frame as Frame;
interface Leds;
interface Get<uint64_t> as LocalExtendedAddress;
interface Ieee802154Debug as Debug;
}
}
implementation
{
enum {
S_IDLE = 0xFF,
};
uint8_t m_payloadAssocRequest[2];
uint8_t m_payloadDisassocRequest[2];
uint8_t m_payloadAssocResponse[MAX_PENDING_ASSOC_RESPONSES][4];
uint8_t m_coordAddrMode;
uint8_t m_assocRespStatus;
uint16_t m_shortAddress;
bool m_associationOngoing;
bool m_disAssociationOngoing;
command error_t Init.init()
{
uint8_t i;
call ResponseTimeout.stop();
m_payloadAssocRequest[0] = S_IDLE;
m_payloadDisassocRequest[0] = S_IDLE;
m_coordAddrMode = 0;
m_associationOngoing = FALSE;
m_disAssociationOngoing = FALSE;
for (i=0; i<MAX_PENDING_ASSOC_RESPONSES; i++)
m_payloadAssocResponse[i][0] = S_IDLE;
return SUCCESS;
}
/* ------------------- MLME_ASSOCIATE Request ------------------- */
command ieee154_status_t MLME_ASSOCIATE.request (
uint8_t LogicalChannel,
uint8_t ChannelPage,
uint8_t CoordAddrMode,
uint16_t CoordPANID,
ieee154_address_t CoordAddress,
ieee154_CapabilityInformation_t CapabilityInformation,
ieee154_security_t *security
)
{
ieee154_status_t status = IEEE154_SUCCESS;
ieee154_txframe_t *txFrame=0;
ieee154_txcontrol_t *txControl=0;
ieee154_address_t srcAddress;
if (security && security->SecurityLevel)
status = IEEE154_UNSUPPORTED_SECURITY;
else if (ChannelPage != IEEE154_SUPPORTED_CHANNELPAGE || LogicalChannel > 26 ||
!(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << LogicalChannel)) ||
(CoordAddrMode != ADDR_MODE_SHORT_ADDRESS && CoordAddrMode != ADDR_MODE_EXTENDED_ADDRESS))
status = IEEE154_INVALID_PARAMETER;
else if (m_associationOngoing || !(txFrame = call TxFramePool.get()))
status = IEEE154_TRANSACTION_OVERFLOW;
else if (!(txControl = call TxControlPool.get())){
call TxFramePool.put(txFrame);
status = IEEE154_TRANSACTION_OVERFLOW;
}
if (status == IEEE154_SUCCESS){
m_assocRespStatus = IEEE154_NO_DATA;
m_shortAddress = 0xFFFF;
call MLME_SET.phyCurrentChannel(LogicalChannel);
call MLME_SET.macPANId(CoordPANID);
m_coordAddrMode = CoordAddrMode;
if (CoordAddrMode == ADDR_MODE_SHORT_ADDRESS)
call MLME_SET.macCoordShortAddress(CoordAddress.shortAddress);
else
call MLME_SET.macCoordExtendedAddress(CoordAddress.extendedAddress);
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
srcAddress.extendedAddress = call LocalExtendedAddress.get();
txFrame->headerLen = call FrameUtility.writeHeader(
txFrame->header->mhr,
CoordAddrMode,
CoordPANID,
&CoordAddress,
ADDR_MODE_EXTENDED_ADDRESS,
0xFFFF,
&srcAddress,
0);
txFrame->header->mhr[MHR_INDEX_FC1] = FC1_ACK_REQUEST | FC1_FRAMETYPE_CMD;
txFrame->header->mhr[MHR_INDEX_FC2] = FC2_SRC_MODE_EXTENDED |
(CoordAddrMode == ADDR_MODE_SHORT_ADDRESS ? FC2_DEST_MODE_SHORT : FC2_DEST_MODE_EXTENDED);
m_payloadAssocRequest[0] = CMD_FRAME_ASSOCIATION_REQUEST;
m_payloadAssocRequest[1] = *((uint8_t*) &CapabilityInformation);
txFrame->payload = m_payloadAssocRequest;
txFrame->payloadLen = 2;
m_associationOngoing = TRUE;
if ((status = call AssociationRequestTx.transmit(txFrame)) != IEEE154_SUCCESS){
m_associationOngoing = FALSE;
call TxFramePool.put(txFrame);
call TxControlPool.put(txControl);
}
}
call Debug.log(LEVEL_INFO, AssociateP_REQUEST, status, 0, 0);
return status;
}
event void AssociationRequestTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) txFrame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(txFrame);
if (status != IEEE154_SUCCESS){
m_associationOngoing = FALSE;
signal MLME_ASSOCIATE.confirm(0xFFFF, status, 0);
} else {
call ResponseTimeout.startOneShot(call MLME_GET.macResponseWaitTime()*IEEE154_aBaseSuperframeDuration);
call Debug.log(LEVEL_INFO, AssociateP_SETTIMER,
call MLME_GET.macResponseWaitTime()*IEEE154_aBaseSuperframeDuration, 0, 0);
}
call Debug.log(LEVEL_INFO, AssociateP_TXDONE, status, 0, 0);
}
event void ResponseTimeout.fired()
{
uint8_t coordAddress[8];
if (!m_associationOngoing)
return;
// have not received an AssociationResponse yet, poll the coordinator now
if (m_coordAddrMode == ADDR_MODE_SHORT_ADDRESS)
*((nxle_uint16_t*) &coordAddress) = call MLME_GET.macCoordShortAddress();
else
call FrameUtility.copyCoordExtendedAddressLE(coordAddress);
if (call DataRequest.poll(m_coordAddrMode, call MLME_GET.macPANId(),
coordAddress, ADDR_MODE_EXTENDED_ADDRESS) != IEEE154_SUCCESS){
m_shortAddress = 0xFFFF;
m_assocRespStatus = IEEE154_TRANSACTION_OVERFLOW;
signal DataRequest.pollDone();
}
}
event message_t* AssociationResponseExtracted.received(message_t* frame, ieee154_txframe_t *txFrame)
{
uint8_t *payload = (uint8_t *) &frame->data;
if (m_associationOngoing){
m_shortAddress = *((nxle_uint16_t*) (payload + 1));
m_assocRespStatus = *(payload + 3);
}
return frame;
}
event void DataRequest.pollDone()
{
if (m_associationOngoing){
call Debug.log(LEVEL_INFO, AssociateP_POLL_DONE, m_payloadAssocRequest[0], m_assocRespStatus, 0);
call ResponseTimeout.stop();
m_associationOngoing = FALSE;
signal MLME_ASSOCIATE.confirm(m_shortAddress, m_assocRespStatus, 0);
}
}
/* ------------------- MLME_ASSOCIATE Response ------------------- */
event message_t* AssociationRequestRx.received(message_t* frame)
{
uint8_t *payload = (uint8_t *) &frame->data;
ieee154_address_t srcAddress;
if (call Frame.getSrcAddrMode(frame) == ADDR_MODE_EXTENDED_ADDRESS &&
call Frame.getSrcAddr(frame, &srcAddress) == SUCCESS)
signal MLME_ASSOCIATE.indication(srcAddress.extendedAddress,
*((ieee154_CapabilityInformation_t*) (payload + 1)), 0);
return frame;
}
command ieee154_status_t MLME_ASSOCIATE.response (
uint64_t deviceAddress,
uint16_t assocShortAddress,
ieee154_association_status_t status,
ieee154_security_t *security
)
{
uint8_t i;
ieee154_status_t txStatus = IEEE154_SUCCESS;
ieee154_txframe_t *txFrame;
ieee154_txcontrol_t *txControl;
ieee154_address_t srcAddress;
for (i=0; i<MAX_PENDING_ASSOC_RESPONSES;i++)
if (m_payloadAssocResponse[i][0] == S_IDLE)
break;
if (i == MAX_PENDING_ASSOC_RESPONSES || !(txFrame = call TxFramePool.get()))
txStatus = IEEE154_TRANSACTION_OVERFLOW;
else if (!(txControl = call TxControlPool.get())){
call TxFramePool.put(txFrame);
txStatus = IEEE154_TRANSACTION_OVERFLOW;
} else {
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
txFrame->payload = m_payloadAssocResponse[i];
srcAddress.extendedAddress = call LocalExtendedAddress.get();
txFrame->headerLen = call FrameUtility.writeHeader(
txFrame->header->mhr,
ADDR_MODE_EXTENDED_ADDRESS,
call MLME_GET.macPANId(),
(ieee154_address_t*) &deviceAddress,
ADDR_MODE_EXTENDED_ADDRESS,
call MLME_GET.macPANId(),
&srcAddress,
1);
txFrame->header->mhr[MHR_INDEX_FC1] = FC1_ACK_REQUEST | FC1_FRAMETYPE_CMD | FC1_PAN_ID_COMPRESSION;
txFrame->header->mhr[MHR_INDEX_FC2] = FC2_SRC_MODE_EXTENDED | FC2_DEST_MODE_EXTENDED;
txFrame->payload[0] = CMD_FRAME_ASSOCIATION_RESPONSE;
*((nxle_uint16_t*) &txFrame->payload[1]) = assocShortAddress;
txFrame->payload[3] = status;
txFrame->payloadLen = 4;
if ((txStatus = call AssociationResponseTx.transmit(txFrame)) != IEEE154_SUCCESS){
txFrame->payload[0] = S_IDLE;
call TxFramePool.put(txFrame);
call TxControlPool.put(txControl);
}
}
return txStatus;
}
event void AssociationResponseTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
ieee154_address_t srcAddress, deviceAddress;
srcAddress.extendedAddress = call LocalExtendedAddress.get();
if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
deviceAddress.shortAddress = *((nxle_uint16_t*) (&(txFrame->header->mhr[MHR_INDEX_ADDRESS]) + 2));
else
call FrameUtility.convertToNative(&deviceAddress.extendedAddress, (&(txFrame->header->mhr[MHR_INDEX_ADDRESS]) + 2));
txFrame->payload[0] = S_IDLE;
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) txFrame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(txFrame);
signal MLME_COMM_STATUS.indication(call MLME_GET.macPANId(), ADDR_MODE_EXTENDED_ADDRESS,
srcAddress, ADDR_MODE_EXTENDED_ADDRESS, deviceAddress,
status, 0);
}
/* ------------------- MLME_DISASSOCIATE (initiating) ------------------- */
command ieee154_status_t MLME_DISASSOCIATE.request (
uint8_t DeviceAddrMode,
uint16_t DevicePANID,
ieee154_address_t DeviceAddress,
ieee154_disassociation_reason_t DisassociateReason,
bool TxIndirect,
ieee154_security_t *security
)
{
ieee154_status_t status = IEEE154_SUCCESS;
ieee154_txframe_t *txFrame=0;
ieee154_txcontrol_t *txControl=0;
ieee154_address_t srcAddress;
if (security && security->SecurityLevel)
status = IEEE154_UNSUPPORTED_SECURITY;
else if (call MLME_GET.macPANId() != DevicePANID ||
(DeviceAddrMode != ADDR_MODE_SHORT_ADDRESS && DeviceAddrMode != ADDR_MODE_EXTENDED_ADDRESS))
status = IEEE154_INVALID_PARAMETER;
else if (m_disAssociationOngoing || !(txFrame = call TxFramePool.get()))
status = IEEE154_TRANSACTION_OVERFLOW;
else if (!(txControl = call TxControlPool.get())){
call TxFramePool.put(txFrame);
status = IEEE154_TRANSACTION_OVERFLOW;
}
if (status == IEEE154_SUCCESS){
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
srcAddress.extendedAddress = call LocalExtendedAddress.get();
txFrame->headerLen = call FrameUtility.writeHeader(
txFrame->header->mhr,
DeviceAddrMode,
call MLME_GET.macPANId(),
&DeviceAddress,
ADDR_MODE_EXTENDED_ADDRESS,
call MLME_GET.macPANId(),
&srcAddress,
TRUE);
txFrame->header->mhr[MHR_INDEX_FC1] = FC1_ACK_REQUEST | FC1_FRAMETYPE_CMD | FC1_PAN_ID_COMPRESSION;
txFrame->header->mhr[MHR_INDEX_FC2] = FC2_SRC_MODE_EXTENDED |
(DeviceAddrMode == ADDR_MODE_SHORT_ADDRESS ? FC2_DEST_MODE_SHORT : FC2_DEST_MODE_EXTENDED);
m_payloadDisassocRequest[0] = CMD_FRAME_DISASSOCIATION_NOTIFICATION;
m_payloadDisassocRequest[1] = DisassociateReason;
txFrame->payload = m_payloadDisassocRequest;
txFrame->payloadLen = 2;
m_disAssociationOngoing = TRUE;
if ((DeviceAddrMode == ADDR_MODE_SHORT_ADDRESS &&
DeviceAddress.shortAddress == call MLME_GET.macCoordShortAddress()) ||
(DeviceAddrMode == ADDR_MODE_EXTENDED_ADDRESS &&
DeviceAddress.extendedAddress == call MLME_GET.macCoordExtendedAddress())){
status = call DisassociationToCoord.transmit(txFrame);
} else if (TxIndirect) {
status = call DisassociationIndirectTx.transmit(txFrame);
} else {
status = call DisassociationDirectTx.transmit(txFrame);
}
if (status != IEEE154_SUCCESS){
m_disAssociationOngoing = FALSE;
call TxFramePool.put(txFrame);
call TxControlPool.put(txControl);
}
}
call Debug.log(LEVEL_INFO, DISSASSOCIATE_REQUEST, status, 0, 0);
return status;
}
event void DisassociationToCoord.transmitDone(ieee154_txframe_t *data, ieee154_status_t status)
{
// transmitted a disassociation notification to our coordinator
uint8_t *mhr = MHR(data), srcAddrOffset = 7;
uint8_t DeviceAddrMode = (mhr[MHR_INDEX_FC2] & FC2_SRC_MODE_MASK) >> FC2_SRC_MODE_OFFSET;
uint16_t DevicePANID = *((nxle_uint16_t*) (&(mhr[MHR_INDEX_ADDRESS])));
ieee154_address_t DeviceAddress;
if ((mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
srcAddrOffset += 6;
call FrameUtility.convertToNative(&DeviceAddress.extendedAddress, &mhr[srcAddrOffset]);
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) data->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(data);
call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0);
m_disAssociationOngoing = FALSE;
signal MLME_DISASSOCIATE.confirm(status, DeviceAddrMode, DevicePANID, DeviceAddress);
}
event void DisassociationIndirectTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status)
{
signal DisassociationDirectTx.transmitDone(data, status);
}
event void DisassociationDirectTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status)
{
// transmitted a disassociation notification to a device
uint8_t *mhr = MHR(data), dstAddrOffset = 5;
uint8_t DeviceAddrMode = (mhr[1] & FC2_DEST_MODE_MASK) >> FC2_DEST_MODE_OFFSET;
uint16_t DevicePANID = *((nxle_uint16_t*) (&(mhr[MHR_INDEX_ADDRESS])));
ieee154_address_t DeviceAddress;
call FrameUtility.convertToNative(&DeviceAddress.extendedAddress, &mhr[dstAddrOffset]);
call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 1, 0);
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) data->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(data);
call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0);
m_disAssociationOngoing = FALSE;
signal MLME_DISASSOCIATE.confirm(status, DeviceAddrMode, DevicePANID, DeviceAddress);
}
/* ------------------- MLME_DISASSOCIATE (receiving) ------------------- */
event message_t* DisassociationDirectRxFromCoord.received(message_t* frame)
{
// received a disassociation notification from the coordinator (direct tx)
ieee154_address_t address;
address.extendedAddress = call LocalExtendedAddress.get();
signal MLME_DISASSOCIATE.indication(address.extendedAddress, frame->data[1], NULL);
return frame;
}
event message_t* DisassociationExtractedFromCoord.received(message_t* frame, ieee154_txframe_t *txFrame)
{
// received a disassociation notification from the coordinator (indirect transmission)
return signal DisassociationDirectRxFromCoord.received(frame);
}
event message_t* DisassociationRxFromDevice.received(message_t* frame)
{
// received a disassociation notification from the device
ieee154_address_t address;
call Debug.log(LEVEL_INFO, DISSASSOCIATE_RX, 0, 0, 0);
if (call Frame.getSrcAddrMode(frame) == ADDR_MODE_EXTENDED_ADDRESS &&
call Frame.getSrcAddr(frame, &address) == SUCCESS)
signal MLME_DISASSOCIATE.indication(address.extendedAddress, frame->data[1], NULL);
return frame;
}
/* ------------------- Defaults ------------------- */
default event void MLME_DISASSOCIATE.indication (
uint64_t DeviceAddress,
ieee154_disassociation_reason_t DisassociateReason,
ieee154_security_t *security
){}
default event void MLME_DISASSOCIATE.confirm (
ieee154_status_t status,
uint8_t DeviceAddrMode,
uint16_t DevicePANID,
ieee154_address_t DeviceAddress
){}
default event void MLME_ASSOCIATE.indication (
uint64_t DeviceAddress,
ieee154_CapabilityInformation_t CapabilityInformation,
ieee154_security_t *security
){}
default event void MLME_ASSOCIATE.confirm (
uint16_t AssocShortAddress,
uint8_t status,
ieee154_security_t *security
){}
default event void MLME_COMM_STATUS.indication (
uint16_t PANId,
uint8_t SrcAddrMode,
ieee154_address_t SrcAddr,
uint8_t DstAddrMode,
ieee154_address_t DstAddr,
ieee154_status_t status,
ieee154_security_t *security
){}
}
--- NEW FILE: BackupP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:22 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
generic module BackupP(typedef backup_t)
{
provides
{
interface SetNow<backup_t*> as Store;
interface GetNow<backup_t*> as Retrieve;
}
}
implementation
{
backup_t m_backup;
async command error_t Store.setNow(backup_t* backup)
{
memcpy(&m_backup, backup, sizeof(backup_t));
return SUCCESS;
}
async command backup_t* Retrieve.getNow()
{
return &m_backup;
}
}
--- NEW FILE: BeaconSynchronizeP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:22 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_DEBUG.h"
module BeaconSynchronizeP
{
provides
{
interface Init as Reset;
interface MLME_SYNC;
interface MLME_BEACON_NOTIFY;
interface MLME_SYNC_LOSS;
interface Get<bool> as IsTrackingBeacons;
interface GetNow<uint32_t> as CapStart;
interface GetNow<ieee154_reftime_t*> as CapStartRefTime;
interface GetNow<uint32_t> as CapLen;
interface GetNow<uint32_t> as CapEnd;
interface GetNow<uint32_t> as CfpEnd;
interface GetNow<uint32_t> as CfpLen;
interface GetNow<uint32_t> as BeaconInterval;
interface GetNow<bool> as IsBLEActive;
interface GetNow<uint16_t> as BLELen;
interface GetNow<uint8_t*> as GtsField;
interface GetNow<uint32_t> as SfSlotDuration;
interface GetNow<uint8_t> as FinalCapSlot;
interface GetNow<uint8_t> as NumGtsSlots;
interface GetNow<bool> as IsRxBroadcastPending;
}
uses
{
interface MLME_GET;
interface MLME_SET;
interface FrameUtility;
interface IEEE154BeaconFrame as BeaconFrame;
interface Alarm<TSymbolIEEE802154,uint32_t> as TrackAlarm;
interface RadioRx as BeaconRx;
interface RadioOff;
interface Get<bool> as IsBeaconEnabledPAN;
interface DataRequest;
interface FrameRx as CoordRealignmentRx;
interface Resource as Token;
interface ResourceTransfer as TokenToCap;
interface TimeCalc;
interface IEEE154Frame as Frame;
interface Leds;
interface Ieee802154Debug as Debug;
}
}
implementation
{
enum {
S_PREPARE = 0,
S_RXNOW = 1,
S_RADIO_OFF = 2,
S_FIRST_SCAN= 3,
RX_DURATION = 1000, // listen for a beacon for RX_DURATION symbols
RX_LAG = 100, // start to listen for a RX_LAG before expected arrival
};
norace bool m_tracking = FALSE;
norace bool m_updatePending = FALSE;
uint8_t m_updateLogicalChannel;
bool m_updateTrackBeacon;
bool m_stopTracking = FALSE;
norace uint8_t m_numBeaconsLost;
uint8_t m_coordAddress[8];
message_t m_beaconBuffer;
norace message_t *m_beaconBufferPtr = &m_beaconBuffer;
norace bool m_beaconSwapBufferReady = TRUE;
norace uint32_t m_beaconInterval;
norace uint32_t m_dt;
norace uint32_t m_lastBeaconRxTime;
norace ieee154_reftime_t m_lastBeaconRxRefTime;
norace uint8_t m_state;
norace uint8_t m_beaconOrder;
norace uint32_t m_sfSlotDuration;
norace uint8_t m_finalCapSlot;
norace uint8_t m_numGtsSlots;
norace uint16_t m_BLELen;
norace bool m_broadcastPending;
uint8_t m_gtsField[1+1+3*7];
task void processBeaconTask();
command error_t Reset.init()
{
if (call Token.isOwner()){
call Leds.led0On(); // internal error
return FAIL;
}
if (m_tracking || m_updatePending)
signal MLME_SYNC_LOSS.indication(
IEEE154_BEACON_LOSS,
call MLME_GET.macPANId(),
call MLME_GET.phyCurrentChannel(),
call MLME_GET.phyCurrentPage(),
NULL);
m_updatePending = m_stopTracking = m_tracking = FALSE;
return SUCCESS;
}
/* ----------------------- MLME-SYNC ----------------------- */
/*
* Allows to synchronize with a coordinator.
*/
command ieee154_status_t MLME_SYNC.request (
uint8_t logicalChannel,
uint8_t channelPage,
bool trackBeacon)
{
uint32_t supportedChannels = IEEE154_SUPPORTED_CHANNELS;
uint32_t currentChannelBit = 1;
currentChannelBit <<= logicalChannel;
if (!(currentChannelBit & supportedChannels) || (call MLME_GET.macPANId() == 0xFFFF) ||
(channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !call IsBeaconEnabledPAN.get())
return IEEE154_INVALID_PARAMETER;
call Debug.log(LEVEL_INFO,SyncP_REQUEST, logicalChannel, channelPage, trackBeacon);
if (!trackBeacon && m_tracking){
// stop tracking after next received beacon
m_stopTracking = TRUE;
} else {
m_stopTracking = FALSE;
m_updateLogicalChannel = logicalChannel;
m_updateTrackBeacon = trackBeacon;
atomic m_updatePending = TRUE;
call Debug.log(LEVEL_INFO,SyncP_RESOURCE_REQUEST, 0, 0, 0);
call Token.request();
}
call Debug.flush();
return IEEE154_SUCCESS;
}
event void Token.granted()
{
bool missed = FALSE;
call Debug.log(LEVEL_INFO,SyncP_GOT_RESOURCE, m_lastBeaconRxTime+m_beaconInterval,
m_beaconInterval, (m_updatePending<<1)+m_tracking);
if (m_updatePending){
m_state = S_FIRST_SCAN;
m_updatePending = FALSE;
m_beaconOrder = call MLME_GET.macBeaconOrder();
if (m_beaconOrder >= 15)
m_beaconOrder = 14;
call MLME_SET.phyCurrentChannel(m_updateLogicalChannel);
m_tracking = m_updateTrackBeacon;
m_beaconInterval = ((uint32_t) 1 << m_beaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration;
m_dt = m_beaconInterval;
m_numBeaconsLost = IEEE154_aMaxLostBeacons; // will be reset when beacon is received
call Debug.log(LEVEL_INFO,SyncP_UPDATING, call MLME_GET.macCoordShortAddress(),
call MLME_GET.macPANId(), m_updateLogicalChannel);
} else {
m_state = S_PREPARE;
if (!m_tracking){
call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0);
call Token.release();
return;
}
while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)){ // missed a beacon
call Debug.log(LEVEL_INFO,SyncP_BEACON_MISSED_1, m_lastBeaconRxTime, m_dt, missed);
m_dt += m_beaconInterval;
m_numBeaconsLost++;
missed = TRUE;
}
if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
post processBeaconTask();
return;
}
if (missed){
call Token.request();
call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, m_lastBeaconRxTime, m_dt, missed);
call Token.release();
return;
}
}
if (!call RadioOff.isOff())
call RadioOff.off();
else
signal RadioOff.offDone();
}
async event void TrackAlarm.fired()
{
call Debug.log(LEVEL_IMPORTANT,SyncP_SWITCHOFF, 0,0,0);
atomic {
switch (m_state)
{
case S_PREPARE:
call BeaconRx.prepare();
break;
case S_RADIO_OFF:
call Debug.log(LEVEL_INFO, SyncP_SWITCHOFF, 0, 0,0);
call RadioOff.off();
break;
}
}
}
async event void BeaconRx.prepareDone()
{
if (m_state == S_FIRST_SCAN){
m_state = S_RADIO_OFF;
atomic {
call BeaconRx.receive(NULL, 0);
call TrackAlarm.start((((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) *
(uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons);
}
} else {
m_state = S_RADIO_OFF;
call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG);
call Debug.log(LEVEL_IMPORTANT,SyncP_RX_ON, call TrackAlarm.getNow(),m_lastBeaconRxTime+m_dt,RX_LAG);
call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + RX_DURATION);
}
}
event message_t* BeaconRx.received(message_t *frame, ieee154_reftime_t *timestamp)
{
uint8_t *mhr = MHR(frame);
call Debug.log(LEVEL_INFO,SyncP_RX_PACKET,*((nxle_uint32_t*) &mhr[MHR_INDEX_ADDRESS]),
mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK,mhr[MHR_INDEX_SEQNO]);
if (!m_beaconSwapBufferReady || !call FrameUtility.isBeaconFromCoord(frame))
{
return frame;
} else {
message_t *tmp = m_beaconBufferPtr;
call TrackAlarm.stop();
m_beaconSwapBufferReady = FALSE;
m_beaconBufferPtr = frame;
if (timestamp != NULL)
memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_reftime_t));
call RadioOff.off();
return tmp;
}
}
async event void RadioOff.offDone()
{
if (m_state == S_FIRST_SCAN)
call BeaconRx.prepare();
else if (m_state == S_PREPARE)
call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY);
else
post processBeaconTask();
}
task void processBeaconTask()
{
// valid beacon timestamp is pre-condition for slotted CSMA-CA
if (m_beaconSwapBufferReady || !call Frame.isTimestampValid(m_beaconBufferPtr)){
// missed a beacon!
m_numBeaconsLost++;
m_dt += m_beaconInterval;
call Debug.log(LEVEL_IMPORTANT, SyncP_BEACON_MISSED_3,m_numBeaconsLost,0,m_lastBeaconRxTime);
if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
m_tracking = FALSE;
call Debug.log(LEVEL_IMPORTANT, SyncP_LOST_SYNC,0,0,0);
call Leds.led2Off();
signal MLME_SYNC_LOSS.indication(
IEEE154_BEACON_LOSS,
call MLME_GET.macPANId(),
call MLME_GET.phyCurrentChannel(),
call MLME_GET.phyCurrentPage(),
NULL // security
);
} else
call Token.request(); // make another request again (before giving the token up)
call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0);
call Token.release();
} else {
// got the beacon!
uint8_t *payload = (uint8_t *) m_beaconBufferPtr->data;
ieee154_macAutoRequest_t autoRequest = call MLME_GET.macAutoRequest();
uint8_t pendAddrSpecOffset = 3 + (((payload[2] & 7) > 0) ? 1 + (payload[2] & 7) * 3: 0); // skip GTS
uint8_t pendAddrSpec = payload[pendAddrSpecOffset];
uint8_t *beaconPayload = payload + pendAddrSpecOffset + 1;
uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconBufferPtr);
uint8_t pendingAddrMode = ADDR_MODE_NOT_PRESENT;
uint8_t coordBeaconOrder;
uint8_t *mhr = MHR(m_beaconBufferPtr);
uint8_t frameLen = ((uint8_t*) m_beaconBufferPtr)[0] & FRAMECTL_LENGTH_MASK;
uint8_t gtsFieldLength;
uint32_t timestamp = call Frame.getTimestamp(m_beaconBufferPtr);
call Debug.log(LEVEL_INFO, SyncP_BEACON_RX, m_lastBeaconRxTime, timestamp, mhr[2]);
m_numGtsSlots = (payload[2] & 7);
gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
m_lastBeaconRxTime = timestamp + IEEE154_SYNC_SYMBOL_OFFSET - IEEE154_SYMBOLS_PER_OCTET - IEEE154_PREAMBLE_LENGTH;
m_finalCapSlot = (payload[1] & 0x0F);
m_sfSlotDuration = (((uint32_t) 1) << ((payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration;
memcpy(m_gtsField, &payload[2], gtsFieldLength);
// check for battery life extension
if (payload[1] & 0x10){
// BLE is active; calculate the time offset from slot0
m_BLELen = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET;
if (frameLen > IEEE154_aMaxSIFSFrameSize)
m_BLELen += call MLME_GET.macMinLIFSPeriod();
else
m_BLELen += call MLME_GET.macMinSIFSPeriod();
m_BLELen += call MLME_GET.macBattLifeExtPeriods();
} else
m_BLELen = 0;
m_broadcastPending = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE;
coordBeaconOrder = (payload[0] & 0x0F);
m_dt = m_beaconInterval = ((uint32_t) 1 << coordBeaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration;
if (m_stopTracking){
m_tracking = FALSE;
call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0);
call Token.release();
} else {
error_t req = call Token.request();
call Debug.log(LEVEL_INFO,SyncP_TRANSFER_RESOURCE, req, 0, 0);
call TokenToCap.transfer();
}
if (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK)
beaconPayload += (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) * 2;
if (pendAddrSpec & PENDING_ADDRESS_EXT_MASK)
beaconPayload += ((pendAddrSpec & PENDING_ADDRESS_EXT_MASK) >> 4) * 8;
// check for pending data (once we signal MLME_BEACON_NOTIFY we cannot
// touch the frame anymore)
if (autoRequest)
pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconBufferPtr);
if (pendingAddrMode != ADDR_MODE_NOT_PRESENT){
// the coord has pending data
uint8_t CoordAddrMode;
uint16_t CoordPANId;
uint8_t *CoordAddress;
uint8_t SrcAddrMode = pendingAddrMode;
if ((mhr[MHR_INDEX_FC2] & FC2_SRC_MODE_MASK) == FC2_SRC_MODE_SHORT)
CoordAddrMode = ADDR_MODE_SHORT_ADDRESS;
else
CoordAddrMode = ADDR_MODE_EXTENDED_ADDRESS;
CoordAddress = &(mhr[MHR_INDEX_ADDRESS+2]);
CoordPANId = *((nxle_uint16_t*) &(mhr[MHR_INDEX_ADDRESS]));
call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode);
}
// Beacon Tracking: update state
call Debug.log(LEVEL_INFO, SyncP_NEXT_RX_TIME, 0, timestamp, m_beaconInterval);
m_numBeaconsLost = 0;
// TODO: check PAN ID conflict here?
if (!autoRequest || beaconPayloadSize)
m_beaconBufferPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconBufferPtr);
m_beaconSwapBufferReady = TRUE;
}
}
command bool IsTrackingBeacons.get(){ return m_tracking;}
default event message_t* MLME_BEACON_NOTIFY.indication (message_t* frame){return frame;}
default event void MLME_SYNC_LOSS.indication (
ieee154_status_t lossReason,
uint16_t panID,
uint8_t logicalChannel,
uint8_t channelPage,
ieee154_security_t *security){}
event void DataRequest.pollDone(){}
async command uint8_t* GtsField.getNow() { return m_gtsField; }
async command uint32_t SfSlotDuration.getNow() { return m_sfSlotDuration; }
async command uint8_t FinalCapSlot.getNow() { return m_finalCapSlot; }
async command uint32_t CapStart.getNow() { return m_lastBeaconRxTime; }
async command ieee154_reftime_t* CapStartRefTime.getNow() { return &m_lastBeaconRxRefTime; }
async command uint32_t CapLen.getNow() { return call SfSlotDuration.getNow() * (call FinalCapSlot.getNow() + 1);}
async command uint32_t CapEnd.getNow()
{
return call CapStart.getNow() + call CapLen.getNow();
}
async command uint32_t CfpEnd.getNow()
{
return call CapStart.getNow() + call SfSlotDuration.getNow() * IEEE154_aNumSuperframeSlots;
}
async command uint32_t CfpLen.getNow()
{
return call SfSlotDuration.getNow() * (15 - call FinalCapSlot.getNow());
}
async command uint32_t BeaconInterval.getNow()
{
return m_beaconInterval;
}
async command uint8_t NumGtsSlots.getNow() { return m_numGtsSlots; }
async command bool IsBLEActive.getNow(){ return m_BLELen>0;}
async command uint16_t BLELen.getNow(){ return m_BLELen;}
async command bool IsRxBroadcastPending.getNow() { return m_broadcastPending; }
event message_t* CoordRealignmentRx.received(message_t* frame)
{
uint8_t *payload = call Frame.getPayload(frame);
ieee154_macPANId_t panID = *(nxle_uint16_t*) &payload[1];
if (panID == call MLME_GET.macPANId())
signal MLME_SYNC_LOSS.indication(
IEEE154_REALIGNMENT, // LossReason
panID, // PANId
payload[5], // LogicalChannel,
call Frame.getPayloadLength(frame) == 9 ? payload[8] : call MLME_GET.phyCurrentPage(),
NULL
);
return frame;
}
}
--- NEW FILE: BeaconTransmitP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_PHY.h"
module BeaconTransmitP
{
provides
{
interface Init as Reset;
interface MLME_START;
interface WriteBeaconField as SuperframeSpecWrite;
interface Get<bool> as IsSendingBeacons;
interface GetNow<uint32_t> as CapStart;
interface GetNow<ieee154_reftime_t*> as CapStartRefTime;
interface GetNow<uint32_t> as CapLen;
interface GetNow<uint32_t> as CapEnd;
interface GetNow<uint32_t> as CfpEnd;
interface GetNow<uint32_t> as CfpLen;
interface GetNow<bool> as IsBLEActive;
interface GetNow<uint16_t> as BLELen;
interface GetNow<uint8_t*> as GtsField;
interface GetNow<uint32_t> as SfSlotDuration;
interface GetNow<uint32_t> as BeaconInterval;
interface GetNow<uint8_t> as FinalCapSlot;
interface GetNow<uint8_t> as NumGtsSlots;
interface GetNow<bool> as BeaconFramePendingBit;
interface IEEE154TxBeaconPayload;
} uses {
interface Notify<bool> as GtsSpecUpdated;
interface Notify<bool> as PendingAddrSpecUpdated;
interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
interface Alarm<TSymbolIEEE802154,uint32_t> as BeaconTxAlarm;
interface Timer<TSymbolIEEE802154> as BeaconPayloadUpdateTimer;
interface RadioOff;
interface Get<bool> as IsBeaconEnabledPAN;
interface RadioTx as BeaconTx;
interface MLME_GET;
interface MLME_SET;
interface Resource as Token;
interface ResourceTransfer as TokenToBroadcast;
interface FrameTx as RealignmentBeaconEnabledTx;
interface FrameTx as RealignmentNonBeaconEnabledTx;
interface FrameRx as BeaconRequestRx;
interface WriteBeaconField as GtsInfoWrite;
interface WriteBeaconField as PendingAddrWrite;
interface FrameUtility;
interface Get<bool> as IsTrackingBeacons;
interface GetNow<uint32_t> as LastBeaconRxTime;
interface GetNow<ieee154_reftime_t*> as LastBeaconRxRefTime;
interface Ieee802154Debug as Debug;
interface Set<ieee154_macSuperframeOrder_t> as SetMacSuperframeOrder;
interface Set<ieee154_macBeaconTxTime_t> as SetMacBeaconTxTime;
interface Set<ieee154_macPanCoordinator_t> as SetMacPanCoordinator;
interface GetSet<ieee154_txframe_t*> as GetSetRealignmentFrame;
interface GetNow<bool> as IsBroadcastReady;
interface TimeCalc;
interface Leds;
}
}
implementation
{
enum {
MAX_BEACON_PAYLOAD_SIZE = IEEE154_aMaxBeaconOverhead + IEEE154_aMaxBeaconPayloadLength,
REQUEST_UPDATE_SF = 0x01,
REQUEST_REALIGNMENT = 0x02,
REQUEST_CONFIRM_PENDING = 0x04,
REQUEST_REALIGNMENT_DONE_PENDING = 0x08,
MODIFIED_SF_SPEC = 0x01,
MODIFIED_GTS_FIELD = 0x02,
MODIFIED_PENDING_ADDR_FIELD = 0x04,
MODIFIED_SPECS_MASK = 0x0F,
MODIFIED_BEACON_PAYLOAD = 0x10,
MODIFIED_BEACON_PAYLOAD_NEW = 0x20,
MODIFIED_BEACON_PAYLOAD_MASK = 0xF0,
S_TX_IDLE = 0,
S_TX_LOCKED = 1,
S_TX_WAITING = 2,
};
norace ieee154_txframe_t m_beaconFrame;
ieee154_header_t m_header;
uint8_t m_payload[MAX_BEACON_PAYLOAD_SIZE];
ieee154_metadata_t m_metadata;
uint8_t m_gtsField[1+1+3*7];
void *m_updateBeaconPayload;
uint8_t m_updateBeaconOffset;
uint8_t m_updateBeaconLength;
uint8_t m_beaconPayloadLen;
uint8_t m_pendingAddrLen;
uint8_t m_pendingGtsLen;
norace uint8_t m_requests; // TODO: check why norace?
norace uint8_t m_txState;
uint8_t m_payloadState;
norace bool m_txOneBeaconImmediately;
uint16_t m_PANId;
norace uint32_t m_startTime;
uint8_t m_logicalChannel;
norace uint8_t m_beaconOrder;
norace uint8_t m_superframeOrder;
ieee154_macBattLifeExt_t m_batteryLifeExtension;
bool m_PANCoordinator;
norace uint32_t m_beaconInterval;
norace uint32_t m_previousBeaconInterval;
norace uint32_t m_dt;
norace uint8_t m_bsn;
norace uint32_t m_lastBeaconTxTime;
norace ieee154_reftime_t m_lastBeaconTxRefTime;
norace uint32_t m_coordCapLen;
norace uint32_t m_coordCfpEnd;
norace uint32_t m_sfSlotDuration;
norace uint8_t m_finalCAPSlot;
norace uint8_t m_numGtsSlots;
norace uint16_t m_BLELen;
norace ieee154_macBattLifeExtPeriods_t m_battLifeExtPeriods;
norace bool m_framePendingBit;
uint16_t m_updatePANId;
uint8_t m_updateLogicalChannel;
uint32_t m_updateStartTime;
uint8_t m_updateBeaconOrder;
uint8_t m_updateSuperframeOrder;
bool m_updatePANCoordinator;
bool m_updateBatteryLifeExtension;
task void txDoneTask();
task void signalStartConfirmSuccessTask();
void prepareNextBeaconTransmission();
void continueStartRequest();
void finishRealignment(ieee154_txframe_t *frame, ieee154_status_t status);
command error_t Reset.init()
{
m_beaconFrame.header = &m_header;
m_beaconFrame.headerLen = 0;
m_beaconFrame.payload = m_payload;
m_beaconFrame.payloadLen = 0;
m_beaconFrame.metadata = &m_metadata;
m_updateBeaconPayload = 0;
m_updateBeaconLength = 0;
m_requests = m_payloadState = m_txState = 0;
m_PANCoordinator = FALSE;
m_beaconPayloadLen = m_pendingAddrLen = m_pendingGtsLen = 0;
m_gtsField[0] = 0;
m_finalCAPSlot = 15;
m_beaconOrder = 15;
call BeaconPayloadUpdateTimer.stop();
call BeaconTxAlarm.stop();
return SUCCESS;
}
/* ----------------------- MLME-START ----------------------- */
/* "The MLME-START.request primitive allows the PAN coordinator to initiate a
* new PAN or to begin using a new superframe configuration. This primitive may
* also be used by a device already associated with an existing PAN to begin
* using a new superframe configuration." (IEEE 802.15.4-2006 Sect. 7.1.14.1)
**/
command ieee154_status_t MLME_START.request (
uint16_t panID,
uint8_t logicalChannel,
uint8_t channelPage,
uint32_t startTime,
uint8_t beaconOrder,
uint8_t superframeOrder,
bool panCoordinator,
bool batteryLifeExtension,
bool coordRealignment,
ieee154_security_t *coordRealignSecurity,
ieee154_security_t *beaconSecurity)
{
ieee154_macShortAddress_t shortAddress = call MLME_GET.macShortAddress();
ieee154_status_t status = IEEE154_SUCCESS;
if ((coordRealignSecurity && coordRealignSecurity->SecurityLevel) ||
(beaconSecurity && beaconSecurity->SecurityLevel))
status = IEEE154_UNSUPPORTED_SECURITY;
else if (shortAddress == 0xFFFF)
status = IEEE154_NO_SHORT_ADDRESS;
else if (logicalChannel > 26 || beaconOrder > 15 ||
(channelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
!(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << logicalChannel)) ||
(superframeOrder > beaconOrder))
status = IEEE154_INVALID_PARAMETER;
else if (startTime && !call IsTrackingBeacons.get())
status = IEEE154_TRACKING_OFF;
else if (startTime && 0xFF000000)
status = IEEE154_INVALID_PARAMETER;
else if (m_requests & (REQUEST_CONFIRM_PENDING | REQUEST_UPDATE_SF))
status = IEEE154_TRANSACTION_OVERFLOW;
else if ((call IsBeaconEnabledPAN.get() && beaconOrder > 14) ||
(!call IsBeaconEnabledPAN.get() && beaconOrder < 15))
status = IEEE154_INVALID_PARAMETER;
else {
// new configuration *will* be put in operation
status = IEEE154_SUCCESS;
if (panCoordinator)
startTime = 0; // start immediately
call Debug.log(LEVEL_INFO, StartP_REQUEST, logicalChannel, beaconOrder, superframeOrder);
if (beaconOrder == 15){
// beaconless PAN
superframeOrder = 15;
}
m_updatePANId = panID;
m_updateLogicalChannel = logicalChannel;
m_updateStartTime = startTime;
m_updateBeaconOrder = beaconOrder;
m_updateSuperframeOrder = superframeOrder;
m_updatePANCoordinator = panCoordinator;
m_updateBatteryLifeExtension = batteryLifeExtension;
m_requests = (REQUEST_CONFIRM_PENDING | REQUEST_UPDATE_SF); // lock
if (coordRealignment)
m_requests |= REQUEST_REALIGNMENT;
if (!call IsSendingBeacons.get())
call Token.request();
}
return status;
}
void continueStartRequest()
{
uint8_t offset;
ieee154_macShortAddress_t shortAddress;
bool isShortAddr;
// (1) coord realignment?
if (m_requests & REQUEST_REALIGNMENT){
ieee154_txframe_t *realignmentFrame = call GetSetRealignmentFrame.get();
m_requests &= ~REQUEST_REALIGNMENT;
if (realignmentFrame == NULL){
// allocation failed!
m_requests = 0;
signal MLME_START.confirm(IEEE154_TRANSACTION_OVERFLOW);
return;
}
// set the payload portion of the realignmentFrame
// (the header fields are already set correctly)
realignmentFrame->payload[0] = CMD_FRAME_COORDINATOR_REALIGNMENT;
*((nxle_uint16_t*) &realignmentFrame->payload[1]) = m_updatePANId;
*((nxle_uint16_t*) &realignmentFrame->payload[3]) = call MLME_GET.macShortAddress();
realignmentFrame->payload[5] = m_updateLogicalChannel;
*((nxle_uint16_t*) &realignmentFrame->payload[6]) = 0xFFFF;
realignmentFrame->payloadLen = 8;
if (call IsSendingBeacons.get()){
// we're already transmitting beacons; the realignment frame
// must be sent (broadcast) after the next beacon
if (call RealignmentBeaconEnabledTx.transmit(realignmentFrame) != IEEE154_SUCCESS){
m_requests = 0;
call GetSetRealignmentFrame.set(realignmentFrame);
signal MLME_START.confirm(IEEE154_TRANSACTION_OVERFLOW);
} else {
// The realignment frame will be transmitted immediately after
// the next beacon - the result will be signalled in
// RealignmentBeaconEnabledTx.transmitDone(). Only then the superframe
// structure is updated and MLME_START.confirm signalled.
m_requests |= REQUEST_REALIGNMENT_DONE_PENDING; // lock
}
} else {
// send realignment frame in unslotted csma-ca now
if (call RealignmentNonBeaconEnabledTx.transmit(realignmentFrame) != IEEE154_SUCCESS){
m_requests = 0;
call GetSetRealignmentFrame.set(realignmentFrame);
signal MLME_START.confirm(IEEE154_TRANSACTION_OVERFLOW);
} else {
// A realignment frame will be transmitted now, the result will
// be signalled in RealignmentNonBeaconEnabledTx.transmitDone(). Only
// then the superframe structure is updated and MLME_START.confirm
// signalled.
m_requests |= REQUEST_REALIGNMENT_DONE_PENDING; // lock
}
}
return;
}
// (2) update internal state
m_startTime = m_updateStartTime;
m_txOneBeaconImmediately = FALSE;
m_previousBeaconInterval = 0;
if (m_startTime){
m_lastBeaconTxRefTime = *call LastBeaconRxRefTime.getNow();
m_lastBeaconTxTime = call LastBeaconRxTime.getNow();
} else {
// no StartTime defined by next higher layer - but
// if a realignment frame was transmitted, the next
// beacon tx time must take the old BI into consideration
if (m_requests & REQUEST_REALIGNMENT_DONE_PENDING)
m_previousBeaconInterval = m_beaconInterval;
else
m_txOneBeaconImmediately = TRUE;
}
m_PANId = m_updatePANId;
m_logicalChannel = m_updateLogicalChannel;
m_beaconOrder = m_updateBeaconOrder;
m_superframeOrder = m_updateSuperframeOrder;
m_PANCoordinator = m_updatePANCoordinator;
if (m_beaconOrder < 15){
m_batteryLifeExtension = m_updateBatteryLifeExtension;
m_beaconInterval = ((uint32_t) 1 << m_updateBeaconOrder) * IEEE154_aBaseSuperframeDuration;
} else {
m_batteryLifeExtension = FALSE;
m_beaconInterval = 0;
}
m_txState = S_TX_IDLE;
m_bsn = call MLME_GET.macBSN()+1;
m_battLifeExtPeriods = call MLME_GET.macBattLifeExtPeriods();
// (3) update PIB
call MLME_SET.macBeaconOrder(m_beaconOrder);
call SetMacSuperframeOrder.set(m_superframeOrder);
call MLME_SET.macPANId(m_PANId);
call MLME_SET.phyCurrentChannel(m_logicalChannel);
if (m_beaconOrder < 15)
call MLME_SET.macBattLifeExt(m_batteryLifeExtension);
call SetMacPanCoordinator.set(m_PANCoordinator);
// (4) assemble beacon header and payload
shortAddress = call MLME_GET.macShortAddress();
isShortAddr = (shortAddress != 0xFFFE);
m_beaconFrame.header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_BEACON;
m_beaconFrame.header->mhr[MHR_INDEX_FC2] = isShortAddr ? FC2_SRC_MODE_SHORT : FC2_SRC_MODE_EXTENDED;
offset = MHR_INDEX_ADDRESS;
*((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = m_PANId;
offset += sizeof(ieee154_macPANId_t);
if (isShortAddr){
*((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = shortAddress;
offset += sizeof(ieee154_macShortAddress_t);
} else {
call FrameUtility.copyLocalExtendedAddressLE(&m_beaconFrame.header->mhr[offset]);
offset += 8;
}
m_beaconFrame.headerLen = offset;
m_payloadState |= MODIFIED_SPECS_MASK; // update beacon payload
signal BeaconPayloadUpdateTimer.fired(); // assemble initial beacon payload
if (m_beaconOrder < 15){
// beacon-enabled PAN, signal confirm after next
// beacon has been transmitted (see MSC, Fig. 38)
m_requests = REQUEST_CONFIRM_PENDING;
} else {
// beaconless PAN, we're done
m_requests = 0;
signal MLME_START.confirm(IEEE154_SUCCESS);
}
}
task void grantedTask()
{
signal Token.granted();
}
event void Token.granted()
{
call Debug.log(LEVEL_INFO, StartP_GOT_RESOURCE, m_lastBeaconTxTime, m_beaconInterval, m_requests);
if (m_requests & REQUEST_REALIGNMENT_DONE_PENDING){
// unlikely to occur: we have not yet received a done()
// event after sending out a realignment frame
post grantedTask(); // spin
return;
}
if (m_requests & REQUEST_UPDATE_SF){
m_requests &= ~REQUEST_UPDATE_SF;
continueStartRequest();
call Debug.log(LEVEL_INFO, StartP_UPDATE_STATE, 0, 0, 0);
}
if (call RadioOff.isOff())
prepareNextBeaconTransmission();
else
call RadioOff.off();
}
async event void RadioOff.offDone()
{
prepareNextBeaconTransmission();
}
void prepareNextBeaconTransmission()
{
if (m_txState == S_TX_LOCKED){
// have not had time to finish processing the last sent beacon
post grantedTask();
call Debug.log(LEVEL_CRITICAL, StartP_OWNER_TOO_FAST, 0, 0, 0);
return;
} else if (m_beaconOrder > 14){
call Token.release();
} else {
atomic {
m_txState = S_TX_WAITING;
if (m_txOneBeaconImmediately){
signal BeaconTxAlarm.fired();
return;
} else if (m_startTime != 0){
// a new sf spec was put into operation, with a user-defined StartTime
// here m_lastBeaconTxTime is actually the last time a beacon was received
m_dt = m_startTime;
m_startTime = 0;
} else if (m_previousBeaconInterval != 0){
// a new sf spec was put into operation, after a realignment frame was
// broadcast; the next beacon time should still be calculated using the
// old BI (one last time)
m_dt = m_previousBeaconInterval;
m_previousBeaconInterval = 0;
if (m_requests & REQUEST_CONFIRM_PENDING){
// only now the next higher layer is to be informed
m_requests &= ~REQUEST_CONFIRM_PENDING;
post signalStartConfirmSuccessTask();
}
} else {
// the usual case: next beacon tx time = last time + BI
m_dt = m_beaconInterval;
}
while (call TimeCalc.hasExpired(m_lastBeaconTxTime, m_dt)){ // missed sending a beacon
call Debug.log(LEVEL_INFO, StartP_SKIPPED_BEACON, m_lastBeaconTxTime, m_dt, 0);
m_dt += m_beaconInterval;
}
if (m_dt < IEEE154_RADIO_TX_PREPARE_DELAY)
m_dt = IEEE154_RADIO_TX_PREPARE_DELAY;
// don't call BeaconTx.load just yet, otherwise the next
// higher layer cannot modify the beacon payload anymore;
// rather, set an alarm
call BeaconTxAlarm.startAt(m_lastBeaconTxTime, m_dt - IEEE154_RADIO_TX_PREPARE_DELAY);
}
}
}
async event void BeaconTxAlarm.fired()
{
atomic {
switch (m_txState)
{
case S_TX_WAITING:
m_txState = S_TX_LOCKED;
if (call IsBroadcastReady.getNow())
m_beaconFrame.header->mhr[MHR_INDEX_FC1] |= FC1_FRAME_PENDING;
else
m_beaconFrame.header->mhr[MHR_INDEX_FC1] &= ~FC1_FRAME_PENDING;
m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = m_bsn; // update beacon seqno
call Debug.log(LEVEL_INFO, StartP_PREPARE_TX, 0, m_lastBeaconTxTime, 0);
call BeaconTx.load(&m_beaconFrame);
break;
case S_TX_LOCKED:
call Debug.log(LEVEL_INFO, StartP_TRANSMIT, m_lastBeaconTxTime, m_dt, ((uint32_t)m_lastBeaconTxRefTime));
call BeaconTx.transmit(&m_lastBeaconTxRefTime, m_dt, 0, FALSE);
break;
}
}
}
async event void BeaconTx.loadDone()
{
atomic {
call Debug.log(LEVEL_INFO, StartP_PREPARE_TXDONE, 0, m_lastBeaconTxTime, 0);
if (m_txOneBeaconImmediately){
m_txOneBeaconImmediately = FALSE;
call BeaconTx.transmit(0, 0, 0, FALSE); // now!
} else
call BeaconTxAlarm.startAt(m_lastBeaconTxTime, m_dt - IEEE154_RADIO_TX_SEND_DELAY);
}
}
async event void BeaconTx.transmitDone(ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool pendingFlag, error_t error)
{
// Coord CAP has just started...
uint8_t gtsFieldLength;
// Sec. 7.5.1.1: "start of slot 0 is defined as the point at which
// the first symbol of the beacon PPDU is transmitted"
call Debug.log(LEVEL_INFO, StartP_BEACON_TRANSMITTED, frame->metadata->timestamp, m_lastBeaconTxTime, m_dt);
m_lastBeaconTxTime = frame->metadata->timestamp;
memcpy(&m_lastBeaconTxRefTime, referenceTime, sizeof(ieee154_reftime_t));
m_numGtsSlots = (frame->payload[2] & 0x07);
gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
m_finalCAPSlot = (frame->payload[1] & 0x0F);
m_sfSlotDuration = (((uint32_t) 1) << ((frame->payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration;
if (frame->header->mhr[0] & FC1_FRAME_PENDING)
m_framePendingBit = TRUE;
else
m_framePendingBit = FALSE;
memcpy(m_gtsField, &frame->payload[0], gtsFieldLength);
if (frame->payload[1] & 0x10){
// BLE is active; calculate the time offset from slot0
m_BLELen = IEEE154_SHR_DURATION +
(frame->headerLen + frame->payloadLen) * IEEE154_SYMBOLS_PER_OCTET;
if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize)
m_BLELen += IEEE154_MIN_LIFS_PERIOD;
else
m_BLELen += IEEE154_MIN_SIFS_PERIOD;
m_BLELen += m_battLifeExtPeriods;
} else
m_BLELen = 0;
call Token.request(); // register another request, before ...
call TokenToBroadcast.transfer(); // ... we let Broadcast module take over
post txDoneTask();
}
task void txDoneTask()
{
call MLME_SET.macBSN(m_bsn++);
call SetMacBeaconTxTime.set(m_lastBeaconTxTime); // start of slot0, ie. first preamble byte of beacon
call BeaconPayloadUpdateTimer.startOneShotAt(m_lastBeaconTxTime,
(m_beaconInterval>BEACON_PAYLOAD_UPDATE_INTERVAL) ? (m_beaconInterval - BEACON_PAYLOAD_UPDATE_INTERVAL): 0);
if (m_requests & REQUEST_CONFIRM_PENDING){
m_requests &= ~REQUEST_CONFIRM_PENDING;
signal MLME_START.confirm(IEEE154_SUCCESS);
}
m_txState = S_TX_IDLE;
signal IEEE154TxBeaconPayload.beaconTransmitted();
call Debug.flush();
}
/* ----------------------- Beacon Payload ----------------------- */
/*
* All access to the payload fields in the beacon happen
* through a set of temporary variables/flags, and just before
* the frame is loaded into the radio these changes are
* propagated into the actual payload portion of the beacon frame.
*/
command error_t IEEE154TxBeaconPayload.setBeaconPayload(void *beaconPayload, uint8_t length)
{
if (length > IEEE154_aMaxBeaconPayloadLength)
return ESIZE;
else {
if (m_payloadState & MODIFIED_BEACON_PAYLOAD)
return EBUSY;
m_updateBeaconPayload = beaconPayload;
m_updateBeaconLength = length;
m_updateBeaconOffset = 0;
m_payloadState |= (MODIFIED_BEACON_PAYLOAD | MODIFIED_BEACON_PAYLOAD_NEW);
}
return SUCCESS;
}
command const void* IEEE154TxBeaconPayload.getBeaconPayload()
{
return &m_payload[IEEE154_aMaxBeaconOverhead];
}
command uint8_t IEEE154TxBeaconPayload.getBeaconPayloadLength()
{
return m_beaconFrame.payloadLen - (m_pendingAddrLen + m_pendingGtsLen + 2);
}
command error_t IEEE154TxBeaconPayload.modifyBeaconPayload(uint8_t offset, void *buffer, uint8_t bufferLength)
{
uint16_t totalLen = offset + bufferLength;
if (totalLen > IEEE154_aMaxBeaconPayloadLength ||
call IEEE154TxBeaconPayload.getBeaconPayloadLength() < totalLen)
return ESIZE;
else {
if (m_payloadState & MODIFIED_BEACON_PAYLOAD)
return EBUSY;
m_updateBeaconPayload = buffer;
m_updateBeaconOffset = offset;
m_updateBeaconLength = bufferLength;
m_payloadState |= MODIFIED_BEACON_PAYLOAD;
}
return SUCCESS;
}
event void PIBUpdate.notify[uint8_t attributeID](const void* attributeValue)
{
switch (attributeID)
{
case IEEE154_macAssociationPermit:
atomic m_payloadState |= MODIFIED_SF_SPEC;
break;
case IEEE154_macGTSPermit:
atomic m_payloadState |= MODIFIED_GTS_FIELD;
break;
default:
break;
}
}
event void PendingAddrSpecUpdated.notify(bool val)
{
atomic m_payloadState |= MODIFIED_PENDING_ADDR_FIELD;
}
event void GtsSpecUpdated.notify(bool val)
{
atomic m_payloadState |= MODIFIED_GTS_FIELD;
}
uint8_t getNumGtsSlots(uint8_t *gtsInfoField)
{
uint8_t i, num=0;
for (i=0; i<(gtsInfoField[0] & GTS_DESCRIPTOR_COUNT_MASK); i++)
num += ((gtsInfoField[4+i*3] & GTS_LENGTH_MASK) >> GTS_LENGTH_OFFSET);
return num;
}
event void BeaconPayloadUpdateTimer.fired()
{
// in this order the MAC payload is updated:
// (1) pending addresses
// (2) GTS spec
// (3) sf spec
// (4) beacon payload (if there's enough time)
uint8_t len=0, *beaconSpecs = &m_payload[IEEE154_aMaxBeaconOverhead]; // going backwards
uint8_t beaconPayloadUpdated = 0, numGtsSlots = 15 - m_finalCAPSlot;
atomic {
if (m_txState == S_TX_LOCKED)
{
call Debug.log(LEVEL_INFO, StartP_BEACON_UPDATE, 0, 0, m_txState);
return; // too late !
}
if (m_payloadState & MODIFIED_PENDING_ADDR_FIELD){
len = call PendingAddrWrite.getLength();
beaconSpecs -= len;
call PendingAddrWrite.write(beaconSpecs, len);
if (len != m_pendingAddrLen){
m_pendingAddrLen = len;
m_payloadState |= MODIFIED_SPECS_MASK; // need to rewrite specs before
}
} else
beaconSpecs -= m_pendingAddrLen;
if (m_payloadState & MODIFIED_GTS_FIELD){
len = call GtsInfoWrite.getLength();
beaconSpecs -= len;
call GtsInfoWrite.write(beaconSpecs, len);
numGtsSlots = getNumGtsSlots(beaconSpecs);
if (len != m_pendingGtsLen || ((15-numGtsSlots) != m_finalCAPSlot)){
m_pendingGtsLen = len;
m_payloadState |= MODIFIED_SPECS_MASK; // need to rewrite specs before
}
} else
beaconSpecs -= m_pendingGtsLen;
beaconSpecs -= 2; // sizeof SF Spec
if (m_payloadState & MODIFIED_SF_SPEC){
call SuperframeSpecWrite.write(beaconSpecs, 2);
beaconSpecs[1] &= 0xF0; // clear FinalCAPSlot field
beaconSpecs[1] |= ((15-numGtsSlots) & 0x0F); // update FinalCAPSlot field
}
m_beaconFrame.payloadLen = (m_pendingAddrLen + m_pendingGtsLen + 2) + m_beaconPayloadLen;
m_beaconFrame.payload = beaconSpecs;
m_payloadState &= ~MODIFIED_SPECS_MASK; // clear flags
} // end atomic (give BeaconTxAlarm.fired() the chance to execute)
signal IEEE154TxBeaconPayload.aboutToTransmit();
atomic {
if (m_txState == S_TX_LOCKED)
{
call Debug.log(LEVEL_INFO, StartP_BEACON_UPDATE_2, 0, 0, m_txState);
return; // too late !
}
if (m_payloadState & MODIFIED_BEACON_PAYLOAD){
memcpy(&m_payload[IEEE154_aMaxBeaconOverhead + m_updateBeaconOffset],
m_updateBeaconPayload, m_updateBeaconLength);
beaconPayloadUpdated = (m_payloadState & MODIFIED_BEACON_PAYLOAD_MASK);
if (beaconPayloadUpdated & MODIFIED_BEACON_PAYLOAD_NEW)
m_beaconPayloadLen = m_updateBeaconOffset + m_updateBeaconLength;
}
m_beaconFrame.payloadLen = (m_pendingAddrLen + m_pendingGtsLen + 2) + m_beaconPayloadLen;
m_payloadState &= ~MODIFIED_BEACON_PAYLOAD_MASK;
}
if (beaconPayloadUpdated){
if ((beaconPayloadUpdated & MODIFIED_BEACON_PAYLOAD_NEW))
signal IEEE154TxBeaconPayload.setBeaconPayloadDone(m_updateBeaconPayload, m_updateBeaconLength);
else
signal IEEE154TxBeaconPayload.modifyBeaconPayloadDone(m_updateBeaconOffset,
m_updateBeaconPayload, m_updateBeaconLength);
}
}
/* ----------------------- SuperframeSpec ----------------------- */
command uint8_t SuperframeSpecWrite.write(uint8_t *superframeSpecField, uint8_t maxlen)
{
if (call SuperframeSpecWrite.getLength() > maxlen)
return 0;
superframeSpecField[0] = m_beaconOrder | (m_superframeOrder << 4);
superframeSpecField[1] = m_finalCAPSlot;
if (m_PANCoordinator)
superframeSpecField[1] |= SF_SPEC2_PAN_COORD;
if (call MLME_GET.macAssociationPermit())
superframeSpecField[1] |= SF_SPEC2_ASSOCIATION_PERMIT;
return 2;
}
command uint8_t SuperframeSpecWrite.getLength()
{
return 2;
}
/* ----------------------- Realignment ----------------------- */
/* In beacon-enabled mode a realignment frame was broadcast in the CAP
* immediately after the beacon was transmitted. In non-beacon-enabled mode a
* realignment frame was sent using unslotted CSMA. In both cases, if the
* transmission was successful, the superframe spec must be updated now.
**/
event void RealignmentBeaconEnabledTx.transmitDone(ieee154_txframe_t *frame, ieee154_status_t status)
{
finishRealignment(frame, status);
}
event void RealignmentNonBeaconEnabledTx.transmitDone(ieee154_txframe_t *frame, ieee154_status_t status)
{
finishRealignment(frame, status);
}
void finishRealignment(ieee154_txframe_t *frame, ieee154_status_t status)
{
call GetSetRealignmentFrame.set(frame);
if (status == IEEE154_SUCCESS){
continueStartRequest();
m_requests &= ~REQUEST_REALIGNMENT_DONE_PENDING; // unlock
// signal confirm where we calculate the next beacon transmission time
} else {
m_requests = 0;
signal MLME_START.confirm(status);
}
}
/* ----------------------- BeaconRequest ----------------------- */
event message_t* BeaconRequestRx.received(message_t* frame)
{
if (!call IsSendingBeacons.get()){
// transmit the beacon frame using unslotted CSMA-CA
// TODO
}
return frame;
}
/* ----------------------- Defaults, etc. ----------------------- */
task void signalStartConfirmSuccessTask()
{
signal MLME_START.confirm(SUCCESS);
}
command bool IsSendingBeacons.get(){ return m_beaconOrder < 15;}
async command uint32_t BeaconInterval.getNow() { return m_beaconInterval; }
async command uint32_t CapStart.getNow() { return m_lastBeaconTxTime; }
async command ieee154_reftime_t* CapStartRefTime.getNow() { return &m_lastBeaconTxRefTime; }
async command uint32_t CapLen.getNow() { return call SfSlotDuration.getNow() * (call FinalCapSlot.getNow() + 1);}
async command uint32_t CapEnd.getNow()
{
return call CapStart.getNow() + call CapLen.getNow();
}
async command uint32_t CfpEnd.getNow()
{
return call CapStart.getNow() + call SfSlotDuration.getNow() * IEEE154_aNumSuperframeSlots;
}
async command uint32_t CfpLen.getNow()
{
return call SfSlotDuration.getNow() * (15 - call FinalCapSlot.getNow());
}
async command bool IsBLEActive.getNow(){ return m_BLELen>0;}
async command uint16_t BLELen.getNow(){ return m_BLELen;}
async command bool BeaconFramePendingBit.getNow(){ return m_framePendingBit;}
async command uint8_t* GtsField.getNow() { return m_gtsField; }
async command uint32_t SfSlotDuration.getNow() { return m_sfSlotDuration; }
async command uint8_t FinalCapSlot.getNow() { return m_finalCAPSlot; }
async command uint8_t NumGtsSlots.getNow() { return m_numGtsSlots; }
default event void MLME_START.confirm (
ieee154_status_t status
){}
default event void IEEE154TxBeaconPayload.setBeaconPayloadDone(void *beaconPayload, uint8_t length){}
default event void IEEE154TxBeaconPayload.modifyBeaconPayloadDone(uint8_t offset, void *buffer, uint8_t bufferLength){}
default event void IEEE154TxBeaconPayload.aboutToTransmit(){}
default event void IEEE154TxBeaconPayload.beaconTransmitted(){}
}
--- NEW FILE: CapP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_PHY.h"
#include "TKN154_MAC.h"
/**
* This module is responsible for sending/receiving frames during the
* contention access period (CAP in beacon-enabled mode). It does slightly
* different things depending on whether it is the CAP for an outgoing
* superframe (superframeDirection = OUTGOING_SUPERFRAME), i.e. the CAP from
* the perspective of a coordinator after it has transmitted its own beacon; or
* for an incoming superframe (superframeDirection = INCOMING_SUPERFRAME), i.e.
* the CAP from the perspective of a device after it has received a beacon from
* its coordinator (e.g. in the CAP a coordinator will usually listen for
* incoming frames from the devices, and a device will usually switch the
* radio off unless it has a frame to transmit).
*/
generic module CapP(uint8_t superframeDirection)
{
provides
{
interface Init as Reset;
interface FrameTx as CapTx;
interface FrameRx as FrameRx[uint8_t frameType];
interface FrameExtracted as FrameExtracted[uint8_t frameType];
interface FrameTxNow as BroadcastTx;
interface Notify<bool> as WasRxEnabled;
}
uses
{
interface Random;
interface Alarm<TSymbolIEEE802154,uint32_t> as CapEndAlarm;
interface Alarm<TSymbolIEEE802154,uint32_t> as BLEAlarm;
interface Alarm<TSymbolIEEE802154,uint32_t> as IndirectTxWaitAlarm;
interface Alarm<TSymbolIEEE802154,uint32_t> as BroadcastAlarm;
interface Resource as Token;
interface ResourceTransfer as TokenToCfp;
interface ResourceTransferred as TokenTransferred;
interface ResourceRequested as TokenRequested;
interface GetNow<bool> as IsTokenRequested;
interface GetNow<uint32_t> as CapStart;
interface GetNow<ieee154_reftime_t*> as CapStartRefTime;
interface GetNow<uint32_t> as CapLen;
interface GetNow<bool> as IsBLEActive;
interface GetNow<uint16_t> as BLELen;
interface GetNow<bool> as IsRxBroadcastPending;
interface GetNow<bool> as IsRxEnableActive;
interface Notify<bool> as RxEnableStateChange;
interface FrameUtility;
interface RadioTx;
interface RadioRx;
interface RadioOff;
interface Get<bool> as IsBeaconEnabledPAN;
interface MLME_GET;
interface MLME_SET;
interface Ieee802154Debug as Debug;
interface TimeCalc;
interface Leds;
interface SetNow<ieee154_cap_frame_backup_t*> as FrameBackup;
interface GetNow<ieee154_cap_frame_backup_t*> as FrameRestore;
}
}
implementation
{
typedef enum {
SWITCH_OFF,
LOAD_TX,
PREPARE_RX,
DO_NOTHING,
WAIT_FOR_TXDONE,
} next_state_t;
typedef enum {
INDIRECT_TX_ALARM,
BROADCAST_ALARM,
NO_ALARM,
} rx_alarm_t;
enum {
COORD_ROLE = (superframeDirection == OUTGOING_SUPERFRAME),
DEVICE_ROLE = !COORD_ROLE,
};
norace bool m_lock;
norace ieee154_txframe_t *m_currentFrame;
norace ieee154_txframe_t *m_bcastFrame;
norace ieee154_txframe_t *m_lastFrame;
norace ieee154_macMaxBE_t m_BE;
norace ieee154_macMaxCSMABackoffs_t m_allowedBackoffs;
norace ieee154_macMaxBE_t m_macMaxBE;
norace uint16_t m_backoff;
norace uint16_t m_backoffElapsed;
norace ieee154_status_t m_result;
norace uint32_t m_transactionTime;
norace bool m_indirectTxPending = FALSE;
norace bool m_broadcastRxPending;
norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime;
uint16_t generateRandomBackoff(uint8_t BE);
void stopAllAlarms();
next_state_t tryReceive(rx_alarm_t alarmType);
next_state_t tryTransmit();
next_state_t trySwitchOff();
void backupCurrentFrame();
void restoreFrameFromBackup();
void updateState();
void setCurrentFrame(ieee154_txframe_t *frame);
void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error);
task void signalTxDoneTask();
task void setupTxBroadcastTask();
task void wasRxEnabledTask();
command error_t Reset.init()
{
if (call Token.isOwner()){
call Leds.led0On(); // internal error
return FAIL;
}
if (m_currentFrame)
signal CapTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
if (m_lastFrame)
signal CapTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
if (m_bcastFrame)
signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW);
m_currentFrame = m_lastFrame = m_bcastFrame = NULL;
m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
stopAllAlarms();
return SUCCESS;
}
async event void TokenTransferred.transferred()
{
// we got the token, i.e. CAP has just started
uint32_t actualCapLen = call CapLen.getNow();
if (actualCapLen < IEEE154_RADIO_GUARD_TIME){
call Debug.log(LEVEL_IMPORTANT, CapP_TOO_SHORT, superframeDirection, actualCapLen, IEEE154_RADIO_GUARD_TIME);
call TokenToCfp.transfer();
return;
} else {
actualCapLen -= IEEE154_RADIO_GUARD_TIME;
if (DEVICE_ROLE)
m_broadcastRxPending = call IsRxBroadcastPending.getNow();
else {
// COORD_ROLE
if (m_bcastFrame != NULL) {
// we have to transmit a broadcast frame immediately; this
// (possibly) requires a backup of the previously active frame
// and a reinitializing the CSMA parameters -> will do it
// in task context and then continue
m_lock = TRUE;
post setupTxBroadcastTask();
}
}
call CapEndAlarm.startAt(call CapStart.getNow(), actualCapLen);
if (call IsBLEActive.getNow())
call BLEAlarm.startAt(call CapStart.getNow(), call BLELen.getNow());
call Debug.log(LEVEL_IMPORTANT, CapP_SET_CAP_END, call CapStart.getNow(), actualCapLen, call CapStart.getNow()+ actualCapLen);
}
updateState();
}
command ieee154_status_t CapTx.transmit(ieee154_txframe_t *frame)
{
// this frame (DATA or COMMAND) should be transmitted in the CAP
if (m_currentFrame != NULL)
return IEEE154_TRANSACTION_OVERFLOW;
else {
setCurrentFrame(frame);
updateState();
return IEEE154_SUCCESS;
}
}
task void setupTxBroadcastTask()
{
ieee154_macDSN_t tmp;
ieee154_txframe_t *oldFrame = m_currentFrame;
if (COORD_ROLE){
if (m_bcastFrame != NULL){
// broadcasts should be transmitted *immediately* after the beacon,
// which may interrupt a pending transmit operation from the previous
// CAP; back up the last active frame configuration (may be none)
// and restore it after the broadcast frame has been transmitted;
// do this through interfaces and don't wire them for DEVICE_ROLE,
// so we don't waste the RAM of devices
backupCurrentFrame();
setCurrentFrame(m_bcastFrame);
if (oldFrame){
// now the sequence number are out of order... swap them back
tmp = m_bcastFrame->header->mhr[MHR_INDEX_SEQNO];
m_bcastFrame->header->mhr[MHR_INDEX_SEQNO] =
oldFrame->header->mhr[MHR_INDEX_SEQNO];
oldFrame->header->mhr[MHR_INDEX_SEQNO] = tmp;
}
}
}
m_lock = FALSE;
updateState();
}
void setCurrentFrame(ieee154_txframe_t *frame)
{
ieee154_macDSN_t dsn = call MLME_GET.macDSN();
frame->header->mhr[MHR_INDEX_SEQNO] = dsn++;
call MLME_SET.macDSN(dsn);
// m_allowedBackoffs will be decreased in every iteration (at zero the transmission failed)
m_allowedBackoffs = call MLME_GET.macMaxCSMABackoffs();
m_macMaxBE = call MLME_GET.macMaxBE();
m_BE = call MLME_GET.macMinBE();
if (call MLME_GET.macBattLifeExt() && m_BE > 2)
m_BE = 2;
m_transactionTime = IEEE154_SHR_DURATION +
(frame->headerLen + frame->payloadLen) * IEEE154_SYMBOLS_PER_OCTET;
if (frame->header->mhr[0] & FC1_ACK_REQUEST)
m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod +
11 * IEEE154_SYMBOLS_PER_OCTET);
if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize)
m_transactionTime += call MLME_GET.macMinLIFSPeriod();
else
m_transactionTime += call MLME_GET.macMinSIFSPeriod();
m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // initial backoff
m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
m_backoffElapsed = 0;
m_currentFrame = frame;
}
uint16_t generateRandomBackoff(uint8_t BE)
{
// return random number from [0,(2^BE) - 1] (uniform distr.)
uint16_t res = call Random.rand16();
uint16_t mask = 0xFFFF;
mask <<= BE;
mask = ~mask;
res &= mask;
return res;
}
void stopAllAlarms()
{
call CapEndAlarm.stop();
if (DEVICE_ROLE){
call IndirectTxWaitAlarm.stop();
call BroadcastAlarm.stop();
}
call BLEAlarm.stop();
}
/**
* The updateState() function is called whenever some event happened that
* might require a state change; it implements a lock mechanism (m_lock) to
* prevent race conditions. Whenever the lock is set a "done"-event (from a
* RadioTx/RadioRx/RadioOff interface) is pending and will "soon" unset the
* lock (and then updateState() will called again). The updateState()
* function decides about the next state by checking a list of possible
* current states ordered by priority, e.g. it first always checks whether
* the CAP is still active. Calling this function more than necessary can do
* no harm, but it SHOULD be called whenever an event happened that might
* lead to a state change.
*/
void updateState()
{
error_t result = SUCCESS;
next_state_t next;
atomic {
// long atomics are bad... but in this block, once the
// current state has been determined only one branch will
// be taken (no loops, etc.)
if (m_lock || !call Token.isOwner())
return;
m_lock = TRUE; // lock
// Check 1: has the CAP finished?
if (call TimeCalc.hasExpired(call CapStart.getNow(), call CapLen.getNow()-IEEE154_RADIO_GUARD_TIME) ||
!call CapEndAlarm.isRunning()){
if (call RadioOff.isOff()) {
stopAllAlarms(); // may still fire, locked through isOwner()
if (DEVICE_ROLE && m_indirectTxPending)
signal IndirectTxWaitAlarm.fired();
m_broadcastRxPending = FALSE;
if (COORD_ROLE && m_bcastFrame){
// didn't manage to transmit a broadcast
restoreFrameFromBackup();
signalTxBroadcastDone(m_bcastFrame, IEEE154_CHANNEL_ACCESS_FAILURE);
m_bcastFrame = NULL;
}
m_lock = FALSE; // unlock
call TokenToCfp.transfer();
return;
} else
next = SWITCH_OFF;
}
// Check 2: should a broadcast frame be received/transmitted immediately
// at the start of CAP?
else if (DEVICE_ROLE && m_broadcastRxPending){
// receive a broadcast from coordinator
next = tryReceive(BROADCAST_ALARM);
} else if (COORD_ROLE && m_bcastFrame){
next = tryTransmit();
}
// Check 3: was an indirect transmission successfully started
// and are we now waiting for a frame from the coordinator?
else if (DEVICE_ROLE && m_indirectTxPending) {
next = tryReceive(INDIRECT_TX_ALARM);
}
// Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending?
else if (call IsTokenRequested.getNow()) {
if (call RadioOff.isOff()) {
stopAllAlarms(); // may still fire, locked through isOwner()
call Token.release();
next = DO_NOTHING;
} else
next = SWITCH_OFF;
}
// Check 5: is battery life extension (BLE) active and
// has the BLE period expired?
else if (call IsBLEActive.getNow() &&
call TimeCalc.hasExpired(call CapStart.getNow(), call BLELen.getNow()) &&
!call IsRxEnableActive.getNow()) {
next = trySwitchOff();
}
// Check 6: is there a frame ready to transmit?
else if (m_currentFrame != NULL) {
next = tryTransmit();
}
// Check 7: should we be in receive mode?
else if (COORD_ROLE || call IsRxEnableActive.getNow()) {
next = tryReceive(NO_ALARM);
if (next == DO_NOTHING && call IsRxEnableActive.getNow()){
// this means there is an active MLME_RX_ENABLE.request
// and the radio was just switched to Rx mode - signal
// a notify event to inform the next higher layer
post wasRxEnabledTask();
}
}
// Check 8: just make sure the radio is switched off
else {
next = trySwitchOff();
}
// if there is nothing to do, then we must clear the lock
if (next == DO_NOTHING)
m_lock = FALSE;
} // atomic
// put next state in operation (possibly keeping the lock)
switch (next)
{
case SWITCH_OFF: result = call RadioOff.off(); break;
case LOAD_TX: result = call RadioTx.load(m_currentFrame); break;
case PREPARE_RX: result = call RadioRx.prepare(); break;
case WAIT_FOR_TXDONE: break;
case DO_NOTHING: break;
}
if (result != SUCCESS)
call Leds.led0On(); // internal error: could not update state !!!
}
next_state_t tryTransmit()
{
// tries to transmit m_currentFrame using the configuration stored
// in other module variables (m_backoff, etc.)
next_state_t next;
if (call RadioTx.getLoadedFrame() == m_currentFrame){
// the frame is already loaded -> transmit it now (if there's enough time)
uint32_t capLen = call CapLen.getNow(), capStart = call CapStart.getNow();
uint32_t elapsed, totalTime;
totalTime = IEEE154_RADIO_TX_SEND_DELAY +
m_backoff - m_backoffElapsed + m_transactionTime + IEEE154_RADIO_GUARD_TIME;
if (totalTime > capLen)
totalTime = capLen; // CAP is too short
elapsed = call TimeCalc.timeElapsed(capStart, call CapEndAlarm.getNow());
elapsed += (20 - (elapsed % 20)); // round to backoff boundary
if (!call TimeCalc.hasExpired(capStart, capLen - totalTime)){
call RadioTx.transmit(call CapStartRefTime.getNow(),
elapsed + IEEE154_RADIO_TX_SEND_DELAY + m_backoff - m_backoffElapsed,
2,
m_currentFrame->header->mhr[0] & FC1_ACK_REQUEST ? TRUE : FALSE);
next = WAIT_FOR_TXDONE; // ATTENTION: this will NOT clear the lock
} else {
// frame does not fit in remaing portion of the CAP
if (elapsed < call CapLen.getNow()){
m_backoffElapsed += call CapLen.getNow() - elapsed;
if (m_backoffElapsed > m_backoff)
m_backoffElapsed = m_backoff;
}
next = SWITCH_OFF;
}
} else {
// the frame to transmit has not yet been loaded -> load it now
if (!call RadioOff.isOff())
next = SWITCH_OFF;
else {
if (m_lastFrame){
// we just transmitted a frame and have not yet
// signalled the done to the upper layer -> wait
next = DO_NOTHING;
} else
next = LOAD_TX;
}
}
return next;
}
next_state_t tryReceive(rx_alarm_t alarmType)
{
next_state_t next;
if (call RadioRx.isReceiving()){
next = DO_NOTHING;
} else if (call RadioRx.isPrepared()){
call RadioRx.receive(NULL, 0);
switch (alarmType)
{
case INDIRECT_TX_ALARM: call IndirectTxWaitAlarm.start(m_macMaxFrameTotalWaitTime); break;
case BROADCAST_ALARM: call BroadcastAlarm.start(m_macMaxFrameTotalWaitTime); break;
case NO_ALARM: break;
}
next = DO_NOTHING;
} else if (call RadioOff.isOff())
next = PREPARE_RX;
else
next = SWITCH_OFF;
return next;
}
next_state_t trySwitchOff()
{
next_state_t next;
if (call RadioOff.isOff())
next = DO_NOTHING;
else
next = SWITCH_OFF;
return next;
}
async event void RadioTx.loadDone(){ m_lock = FALSE; updateState();}
async event void RadioOff.offDone(){ m_lock = FALSE; updateState();}
async event void RadioRx.prepareDone(){ m_lock = FALSE; updateState();}
async event void CapEndAlarm.fired(){
call Debug.log(LEVEL_IMPORTANT, CapP_CAP_END_FIRED, superframeDirection, 0, 0);
updateState();
}
async event void BLEAlarm.fired(){ updateState();}
event void RxEnableStateChange.notify(bool whatever){ updateState();}
async event void BroadcastAlarm.fired(){ m_broadcastRxPending = FALSE; updateState();}
async event void IndirectTxWaitAlarm.fired()
{
atomic {
if (m_indirectTxPending){
m_indirectTxPending = FALSE;
post signalTxDoneTask();
}
}
}
async event void RadioTx.transmitDone(ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
{
switch (error)
{
case SUCCESS:
m_result = IEEE154_SUCCESS;
if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST &&
((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD){
// just transmitted a data request frame
m_result = IEEE154_NO_DATA; // pessimistic
if (ackPendingFlag){
// the coordinator has data for us; switch to Rx
// to complete the indirect transmission
m_indirectTxPending = TRUE;
m_lastFrame = m_currentFrame;
m_currentFrame = NULL;
if (call RadioRx.prepare() != SUCCESS) // SHOULD succeed
call RadioOff.off();
return;
}
}
break;
case EBUSY:
m_result = IEEE154_CHANNEL_ACCESS_FAILURE;
if (m_allowedBackoffs > 0){
m_allowedBackoffs -= 1;
m_BE += 1;
if (m_BE > m_macMaxBE)
m_BE = m_macMaxBE;
m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // next backoff
m_backoffElapsed = 0;
m_lock = FALSE;
updateState();
return;
}
break;
case ENOACK:
m_result = IEEE154_NO_ACK;
break;
default: break;
}
if (COORD_ROLE && frame == m_bcastFrame){
// signal result of broadcast transmissions immediately
restoreFrameFromBackup();
signalTxBroadcastDone(m_bcastFrame, m_result);
m_bcastFrame = NULL;
} else {
m_lastFrame = m_currentFrame;
m_currentFrame = NULL;
post signalTxDoneTask();
}
m_lock = FALSE;
updateState();
}
task void signalTxDoneTask()
{
ieee154_txframe_t *lastFrame = m_lastFrame;
m_lastFrame = NULL; // only now can a next transmission begin
m_indirectTxPending = FALSE;
if (lastFrame)
signal CapTx.transmitDone(lastFrame, m_result);
updateState();
}
event message_t* RadioRx.received(message_t* frame, ieee154_reftime_t *timestamp)
{
// received a frame during CAP - find out frame type and
// signal it to corresponding client component
uint8_t *payload = (uint8_t *) frame->data;
uint8_t *mhr = MHR(frame);
uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK;
if (frameType == FC1_FRAMETYPE_CMD)
frameType += payload[0];
atomic {
if (DEVICE_ROLE && m_indirectTxPending){
message_t* frameBuf;
call IndirectTxWaitAlarm.stop();
// TODO: check!
//if (frame->payloadLen)
// is this frame from our coordinator? hmm... we cannot say
// with certainty, because we might only know either the
// coordinator extended or short address (and the frame could
// have been sent with the other addressing mode) ??
m_result = IEEE154_SUCCESS;
frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame);
signal IndirectTxWaitAlarm.fired();
return frameBuf;
} else
return signal FrameRx.received[frameType](frame);
}
}
void backupCurrentFrame()
{
ieee154_cap_frame_backup_t backup = {m_currentFrame, m_BE, m_allowedBackoffs,
m_macMaxBE, m_backoff, m_backoffElapsed, m_transactionTime};
call FrameBackup.setNow(&backup);
}
void restoreFrameFromBackup()
{
ieee154_cap_frame_backup_t *backup = call FrameRestore.getNow();
if (backup != NULL){
m_currentFrame = backup->frame;
m_BE = backup->BE;
m_allowedBackoffs = backup->allowedBackoffs;
m_macMaxBE = backup->macMaxBE;
m_backoff = backup->backoff;
m_backoffElapsed = backup->backoffElapsed;
m_transactionTime = backup->transactionTime;
}
}
async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame)
{
// if this command is called then it is (MUST be) called
// only just before the token is transferred to this component
// and it is then be called only once per CAP (max. one broadcast
// is allowed after a beacon transmission)
atomic {
if (!call Token.isOwner() && m_bcastFrame == NULL){
m_bcastFrame = frame;
return IEEE154_SUCCESS;
} else {
call Leds.led0On();
return IEEE154_TRANSACTION_OVERFLOW;
}
}
}
void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error)
{
signal BroadcastTx.transmitNowDone(frame, error);
}
task void wasRxEnabledTask()
{
signal WasRxEnabled.notify(TRUE);
}
async event void TokenRequested.requested() {}
async event void TokenRequested.immediateRequested() {}
event void Token.granted(){}
default event void CapTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status){}
default event message_t* FrameRx.received[uint8_t client](message_t* data){return data;}
default async command bool IsRxEnableActive.getNow(){return FALSE;}
default async command void IndirectTxWaitAlarm.start(uint32_t dt){call Leds.led0On();}
default async command void IndirectTxWaitAlarm.stop(){call Leds.led0On();}
default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();}
default async command void BroadcastAlarm.start(uint32_t dt){call Leds.led0On();}
default async command void BroadcastAlarm.stop(){call Leds.led0On();}
default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();}
default async command bool IsRxBroadcastPending.getNow(){ return FALSE;}
default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status){}
default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame){return msg;}
default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val ){return FAIL;}
default async command ieee154_cap_frame_backup_t* FrameRestore.getNow(){return NULL;}
command error_t WasRxEnabled.enable(){return FAIL;}
command error_t WasRxEnabled.disable(){return FAIL;}
}
--- NEW FILE: CapQueueP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
generic module CapQueueP() {
provides
{
interface Init as Reset;
interface FrameTx[uint8_t client];
interface FrameRx as FrameExtracted[uint8_t client];
interface Purge;
} uses {
interface Queue<ieee154_txframe_t*>;
interface FrameTx as CapTx;
interface FrameRx as SubFrameExtracted;
}
}
implementation
{
task void tryCapTxTask();
bool m_busy;
uint8_t m_client;
command error_t Reset.init()
{
while (call Queue.size()){
ieee154_txframe_t *txFrame = call Queue.dequeue();
signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_OVERFLOW);
}
m_busy = FALSE;
return SUCCESS;
}
command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
{
txFrame->client = client;
if (call Queue.enqueue(txFrame) != SUCCESS)
return IEEE154_TRANSACTION_OVERFLOW;
else {
post tryCapTxTask();
return IEEE154_SUCCESS;
}
}
task void tryCapTxTask()
{
if (!m_busy && call Queue.size()){
ieee154_txframe_t *txFrame = call Queue.head();
if (txFrame->headerLen == 0){
// was purged
call Queue.dequeue();
signal Purge.purgeDone(txFrame, IEEE154_SUCCESS);
post tryCapTxTask();
}
m_client = txFrame->client;
if (call CapTx.transmit(txFrame) == IEEE154_SUCCESS){
m_busy = TRUE;
}
}
}
event void CapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
call Queue.dequeue();
m_busy = FALSE;
signal FrameTx.transmitDone[txFrame->client](txFrame, status);
post tryCapTxTask();
}
event message_t* SubFrameExtracted.received(message_t* frame)
{
// this event is signalled when a frame has been received
// in response to a data request command frame. The transmitDone
// event will be signalled later
return signal FrameExtracted.received[m_client](frame);
}
default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){}
command ieee154_status_t Purge.purge(uint8_t msduHandle)
{
uint8_t qSize = call Queue.size(), i;
if (qSize > 1){
for (i=0; i<qSize-1; i++){
ieee154_txframe_t *txFrame = call Queue.element(i);
if (((txFrame->header->mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_DATA) &&
txFrame->handle == msduHandle){
txFrame->headerLen = 0; // mark as invalid
return IEEE154_SUCCESS;
}
}
}
return IEEE154_INVALID_HANDLE;
}
default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){}
}
--- NEW FILE: CoordBroadcastP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/* This component is responsible for sending broadcast frames from
* a coordinator to devices.
**/
#include "TKN154_MAC.h"
module CoordBroadcastP
{
provides
{
interface Init as Reset;
interface FrameTx as BroadcastDataFrame;
interface FrameTx as RealignmentTx;
interface GetNow<bool> as IsBroadcastReady;
} uses {
interface Queue<ieee154_txframe_t*>;
interface FrameTxNow as CapTransmitNow;
interface ResourceTransfer as TokenToCap;
interface ResourceTransferred as TokenTransferred;
interface GetNow<bool> as BeaconFramePendingBit;
interface Leds;
}
}
implementation
{
norace bool m_lock;
norace ieee154_txframe_t *m_realignmentFrame;
norace ieee154_txframe_t *m_queueHead;
norace ieee154_txframe_t *m_transmittedFrame;
norace ieee154_status_t m_status;
task void transmitNowDoneTask();
command error_t Reset.init()
{
while (call Queue.size())
signal BroadcastDataFrame.transmitDone(call Queue.dequeue(), IEEE154_TRANSACTION_OVERFLOW);
if (m_realignmentFrame)
signal RealignmentTx.transmitDone(m_realignmentFrame, IEEE154_TRANSACTION_OVERFLOW);
m_realignmentFrame = m_queueHead = m_transmittedFrame = NULL;
m_lock = FALSE;
return SUCCESS;
}
command ieee154_status_t BroadcastDataFrame.transmit(ieee154_txframe_t *txFrame)
{
if (call Queue.enqueue(txFrame) != SUCCESS)
return IEEE154_TRANSACTION_OVERFLOW;
atomic {
if (m_queueHead == NULL)
m_queueHead = call Queue.head();
}
return IEEE154_SUCCESS;
}
command ieee154_status_t RealignmentTx.transmit(ieee154_txframe_t *frame)
{
atomic {
if (!m_realignmentFrame){
m_realignmentFrame = frame;
return IEEE154_SUCCESS;
} else
return IEEE154_TRANSACTION_OVERFLOW;
}
}
async command bool IsBroadcastReady.getNow()
{
if (m_lock)
return FALSE;
else
return (m_realignmentFrame != NULL || m_queueHead != NULL);
}
async event void TokenTransferred.transferred()
{
// CAP has started - are there any broadcast frames to be transmitted?
if (call BeaconFramePendingBit.getNow()){
ieee154_txframe_t *broadcastFrame = m_realignmentFrame;
if (broadcastFrame == NULL)
broadcastFrame = m_queueHead;
if (broadcastFrame){
m_lock = TRUE;
call CapTransmitNow.transmitNow(broadcastFrame);
} else
call Leds.led0On(); // internal error!
}
call TokenToCap.transfer();
}
async event void CapTransmitNow.transmitNowDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
m_transmittedFrame = txFrame;
m_status = status;
post transmitNowDoneTask();
}
task void transmitNowDoneTask()
{
if (!m_lock)
return;
if (m_transmittedFrame == m_realignmentFrame){
m_realignmentFrame = NULL;
signal RealignmentTx.transmitDone(m_transmittedFrame, m_status);
} else if (m_transmittedFrame == m_queueHead){
call Queue.dequeue();
m_queueHead = call Queue.head();
signal BroadcastDataFrame.transmitDone(m_transmittedFrame, m_status);
}
m_lock = FALSE;
}
}
--- NEW FILE: CoordRealignmentP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/* "The coordinator realignment command is sent by the PAN coordinator or a
* coordinator either following the reception of an orphan notification command
* from a device that is recognized to be on its PAN or when any of its PAN
* configuration attributes change due to the receipt of an MLME-START.request
* primitive." IEEE 802.15.4-2006, Sec. 7.3.8 **/
#include "TKN154_MAC.h"
module CoordRealignmentP
{
provides
{
interface Init;
interface MLME_ORPHAN;
interface MLME_COMM_STATUS;
interface GetSet<ieee154_txframe_t*> as GetSetRealignmentFrame;
}
uses
{
interface FrameTx as CoordRealignmentTx;
interface FrameRx as OrphanNotificationRx;
interface FrameUtility;
interface MLME_GET;
interface IEEE154Frame as Frame;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface Pool<ieee154_txcontrol_t> as TxControlPool;
interface Get<uint64_t> as LocalExtendedAddress;
}
}
implementation
{
enum {
ORPHAN_RESPONSE,
BEACON_REALIGNMENT,
};
uint8_t m_payload[9];
bool m_busy = FALSE;
void destroyRealignmentFrame(ieee154_txframe_t *frame);
ieee154_txframe_t *newRealignmentFrame(uint8_t type, ieee154_address_t *dstAddress);
command error_t Init.init()
{
return SUCCESS;
}
command ieee154_txframe_t* GetSetRealignmentFrame.get()
{
ieee154_address_t bcastAddr;
bcastAddr.shortAddress = 0xFFFF;
return newRealignmentFrame(BEACON_REALIGNMENT, &bcastAddr);
}
command void GetSetRealignmentFrame.set(ieee154_txframe_t* frame)
{
destroyRealignmentFrame(frame);
}
event message_t* OrphanNotificationRx.received(message_t* frame)
{
ieee154_address_t srcAddress;
if (call Frame.getSrcAddrMode(frame) == ADDR_MODE_EXTENDED_ADDRESS &&
call Frame.getSrcAddr(frame, &srcAddress) == SUCCESS)
signal MLME_ORPHAN.indication (
srcAddress.extendedAddress,
NULL // security
);
return frame;
}
command ieee154_status_t MLME_ORPHAN.response (
uint64_t OrphanAddress,
uint16_t ShortAddress,
bool AssociatedMember,
ieee154_security_t *security
)
{
ieee154_txframe_t *txFrame;
ieee154_status_t txStatus;
ieee154_address_t dstAddress;
dstAddress.extendedAddress = OrphanAddress;
if (!AssociatedMember)
txStatus = IEEE154_SUCCESS;
else if (m_busy || (txFrame = newRealignmentFrame(ORPHAN_RESPONSE, &dstAddress)) != NULL)
txStatus = IEEE154_TRANSACTION_OVERFLOW;
else {
m_busy = TRUE;
txFrame->payload[0] = CMD_FRAME_COORDINATOR_REALIGNMENT;
*((nxle_uint16_t*) &txFrame->payload[1]) = call MLME_GET.macPANId();
*((nxle_uint16_t*) &txFrame->payload[3]) = call MLME_GET.macShortAddress();
txFrame->payload[5] = call MLME_GET.phyCurrentChannel();
*((nxle_uint16_t*) &txFrame->payload[6]) = ShortAddress;
txFrame->payloadLen = 8;
if ((txStatus = call CoordRealignmentTx.transmit(txFrame)) != IEEE154_SUCCESS){
m_busy = FALSE;
destroyRealignmentFrame(txFrame);
}
}
return txStatus;
}
ieee154_txframe_t *newRealignmentFrame(uint8_t type, ieee154_address_t *dstAddress)
{
ieee154_txframe_t *txFrame = NULL;
ieee154_txcontrol_t *txControl;
uint8_t dstAddrMode;
ieee154_address_t srcAddress;
if ((txFrame = call TxFramePool.get()) != NULL){
if ((txControl = call TxControlPool.get()) == NULL){
call TxFramePool.put(txFrame);
txFrame = NULL;
} else {
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
txFrame->payload = m_payload;
txFrame->header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_CMD;
txFrame->header->mhr[MHR_INDEX_FC2] = FC2_SRC_MODE_EXTENDED;
if (type == ORPHAN_RESPONSE){
txFrame->header->mhr[MHR_INDEX_FC2] |= FC2_DEST_MODE_EXTENDED;
dstAddrMode = ADDR_MODE_EXTENDED_ADDRESS;
txFrame->header->mhr[MHR_INDEX_FC1] |= FC1_ACK_REQUEST;
} else {
txFrame->header->mhr[MHR_INDEX_FC2] |= FC2_DEST_MODE_SHORT;
dstAddrMode = ADDR_MODE_SHORT_ADDRESS;
}
srcAddress.extendedAddress = call LocalExtendedAddress.get();
txFrame->headerLen = call FrameUtility.writeHeader(
txFrame->header->mhr,
dstAddrMode,
0xFFFF,
dstAddress,
ADDR_MODE_EXTENDED_ADDRESS,
call MLME_GET.macPANId(),
&srcAddress,
FALSE);
}
}
return txFrame;
}
void destroyRealignmentFrame(ieee154_txframe_t *frame)
{
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) frame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(frame);
}
event void CoordRealignmentTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
uint8_t *mhr = MHR(txFrame);
ieee154_address_t dstAddr;
ieee154_address_t srcAddr;
if (m_busy){
call FrameUtility.convertToNative(&dstAddr.extendedAddress, &mhr[MHR_INDEX_ADDRESS+2]);
call FrameUtility.convertToNative(&srcAddr.extendedAddress, &mhr[MHR_INDEX_ADDRESS+2+8+2]);
signal MLME_COMM_STATUS.indication (
*((nxle_uint16_t*) &txFrame->payload[1]), // PANId
ADDR_MODE_EXTENDED_ADDRESS, // SrcAddrMode
srcAddr,
ADDR_MODE_EXTENDED_ADDRESS, // DstAddrMode
dstAddr,
status,
NULL //security
);
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) txFrame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(txFrame);
m_busy = FALSE;
}
}
default event void MLME_COMM_STATUS.indication (
uint16_t PANId,
uint8_t SrcAddrMode,
ieee154_address_t SrcAddr,
uint8_t DstAddrMode,
ieee154_address_t DstAddr,
ieee154_status_t status,
ieee154_security_t *security
){}
default event void MLME_ORPHAN.indication (
uint64_t OrphanAddress,
ieee154_security_t *security
){}
}
--- NEW FILE: DataP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
module DataP
{
provides
{
interface Init;
interface MCPS_DATA;
interface MCPS_PURGE;
} uses {
interface Get<bool> as IsSendingBeacons;
interface FrameRx as CoordCapRx;
interface FrameTx as DeviceCapTx;
interface FrameTx as CoordCapTx;
interface FrameTx as BroadcastTx;
interface FrameRx as DeviceCapRx;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface FrameTx as DeviceCfpTx;
interface FrameTx as CoordCfpTx;
interface FrameTx as IndirectTx;
interface FrameRx as CoordCfpRx;
interface FrameRx as DeviceCfpRx;
interface FrameUtility;
interface Purge as PurgeDirect;
interface Purge as PurgeIndirect;
interface Purge as PurgeGtsDevice;
interface Purge as PurgeGtsCoord;
interface MLME_GET;
interface Leds;
interface Packet;
interface IEEE154Frame as Frame;
interface Get<uint64_t> as LocalExtendedAddress;
}
}
implementation
{
message_t* dataReceived(message_t* frame);
void finishTxTransaction(ieee154_txframe_t *txFrame, ieee154_status_t status);
command error_t Init.init()
{
return SUCCESS;
}
command ieee154_status_t MCPS_DATA.request (
message_t *frame,
uint8_t payloadLen,
uint8_t msduHandle,
uint8_t txOptions
)
{
uint8_t srcAddrMode = call Frame.getSrcAddrMode(frame);
uint8_t dstAddrMode = call Frame.getDstAddrMode(frame);
ieee154_address_t dstAddr;
ieee154_status_t txStatus;
ieee154_txframe_t *txFrame;
uint8_t sfType=0;
uint8_t *mhr;
if (payloadLen > call Packet.maxPayloadLength())
txStatus = IEEE154_INVALID_PARAMETER;
else if ((!srcAddrMode && !dstAddrMode) ||
(srcAddrMode > ADDR_MODE_EXTENDED_ADDRESS || dstAddrMode > ADDR_MODE_EXTENDED_ADDRESS) ||
(srcAddrMode == ADDR_MODE_RESERVED || dstAddrMode == ADDR_MODE_RESERVED))
txStatus = IEEE154_INVALID_ADDRESS;
else if (!(txFrame = call TxFramePool.get()))
txStatus = IEEE154_TRANSACTION_OVERFLOW;
else {
// construct the DATA frame
txFrame->header = &((message_header_t*) frame->header)->ieee154;
txFrame->payload = (uint8_t*) frame->data;
txFrame->metadata = &((message_metadata_t*) frame->metadata)->ieee154;
txFrame->payloadLen = payloadLen;
mhr = txFrame->header->mhr;
txFrame->headerLen = call Frame.getHeaderLength(frame);
mhr[MHR_INDEX_FC1] &= ~(FC1_FRAMETYPE_MASK | FC1_FRAME_PENDING | FC1_ACK_REQUEST);
mhr[MHR_INDEX_FC1] |= FC1_FRAMETYPE_DATA;
if (txOptions & TX_OPTIONS_ACK)
mhr[MHR_INDEX_FC1] |= FC1_ACK_REQUEST;
mhr[MHR_INDEX_FC2] &= ~FC2_FRAME_VERSION_MASK;
if (payloadLen > IEEE154_aMaxMACSafePayloadSize)
mhr[MHR_INDEX_FC2] |= FC2_FRAME_VERSION_1;
txFrame->handle = msduHandle;
// in case a node is both, coordinator and device (e.g. in a
// cluster-tree topology), it has to be decided whether the frame
// is to be sent in the incoming or outgoing superframe (sf);
// we do this by comparing the destination address to the
// coordinator address in the PIB, if they match the frame is
// sent in the incoming sf otherwise in the outgoing sf
call Frame.getDstAddr(frame, &dstAddr);
if (dstAddrMode == ADDR_MODE_SHORT_ADDRESS){
if (dstAddr.shortAddress == call MLME_GET.macCoordShortAddress())
sfType = INCOMING_SUPERFRAME;
else
sfType = OUTGOING_SUPERFRAME;
} else if (dstAddrMode == ADDR_MODE_EXTENDED_ADDRESS){
if (dstAddr.extendedAddress == call MLME_GET.macCoordExtendedAddress())
sfType = INCOMING_SUPERFRAME;
else
sfType = OUTGOING_SUPERFRAME;
} else if (dstAddrMode == ADDR_MODE_NOT_PRESENT) // to PAN Coord
sfType = INCOMING_SUPERFRAME;
// GTS?
if (txOptions & TX_OPTIONS_GTS){
if (sfType == INCOMING_SUPERFRAME)
txStatus = call DeviceCfpTx.transmit(txFrame);
else
txStatus = call CoordCfpTx.transmit(txFrame);
// indirect transmission?
} else if ((txOptions & TX_OPTIONS_INDIRECT) &&
call IsSendingBeacons.get() &&
(dstAddrMode >= ADDR_MODE_SHORT_ADDRESS)){
if (dstAddrMode == ADDR_MODE_SHORT_ADDRESS && dstAddr.shortAddress == 0xFFFF){
mhr[MHR_INDEX_FC1] &= ~FC1_ACK_REQUEST;
txStatus = call BroadcastTx.transmit(txFrame);
} else
txStatus = call IndirectTx.transmit(txFrame);
// transmission in the CAP
} else
if (sfType == INCOMING_SUPERFRAME)
txStatus = call DeviceCapTx.transmit(txFrame);
else
txStatus = call CoordCapTx.transmit(txFrame);
if (txStatus != IEEE154_SUCCESS){
call TxFramePool.put(txFrame);
}
}
return txStatus;
}
command ieee154_status_t MCPS_PURGE.request (
uint8_t msduHandle
)
{
if (call PurgeDirect.purge(msduHandle) == IEEE154_SUCCESS ||
call PurgeIndirect.purge(msduHandle) == IEEE154_SUCCESS ||
call PurgeGtsDevice.purge(msduHandle) == IEEE154_SUCCESS ||
call PurgeGtsCoord.purge(msduHandle) == IEEE154_SUCCESS)
return IEEE154_SUCCESS;
else
return IEEE154_INVALID_HANDLE;
}
event void PurgeDirect.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
{
finishTxTransaction(data, status);
}
event void PurgeIndirect.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
{
finishTxTransaction(data, status);
}
event void PurgeGtsDevice.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
{
finishTxTransaction(data, status);
}
event void PurgeGtsCoord.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
{
finishTxTransaction(data, status);
}
event message_t* CoordCfpRx.received(message_t* frame)
{
return dataReceived(frame);
}
event message_t* DeviceCfpRx.received(message_t* frame)
{
return dataReceived(frame);
}
event message_t* CoordCapRx.received(message_t* frame)
{
return dataReceived(frame);
}
event message_t* DeviceCapRx.received(message_t* frame)
{
return dataReceived(frame);
}
message_t* dataReceived(message_t* frame)
{
return signal MCPS_DATA.indication( frame );
}
void finishTxTransaction(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
uint8_t handle = txFrame->handle;
uint32_t txTime = txFrame->metadata->timestamp;
message_t *msg = (message_t*) ((uint8_t*) txFrame->header - offsetof(message_t, header));
call TxFramePool.put(txFrame);
signal MCPS_DATA.confirm(msg, handle, status, txTime);
}
event void BroadcastTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
event void DeviceCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
event void DeviceCfpTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
event void CoordCfpTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
event void IndirectTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
finishTxTransaction(txFrame, status);
}
default event void MCPS_DATA.confirm(
message_t *msg,
uint8_t msduHandle,
ieee154_status_t status,
uint32_t Timestamp
){}
default event message_t* MCPS_DATA.indication ( message_t* frame ){ return frame; }
default command ieee154_status_t DeviceCfpTx.transmit(ieee154_txframe_t *data){return IEEE154_INVALID_GTS;}
default command ieee154_status_t CoordCfpTx.transmit(ieee154_txframe_t *data){return IEEE154_INVALID_GTS;}
}
--- NEW FILE: FrameDispatchImplP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:27 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_DEBUG.h"
module FrameDispatchImplP
{
provides
{
interface RadioRx as MacRx[uint8_t client];
interface RadioTx as MacTx[uint8_t client];
interface RadioOff as MacRadioOff[uint8_t client];
} uses {
interface ArbiterInfo;
interface RadioRx as PhyRx;
interface RadioTx as PhyTx;
interface RadioOff as PhyRadioOff;
interface Get<bool> as RadioPromiscuousMode;
interface Leds;
interface Ieee802154Debug as Debug;
}
}
implementation
{
/* ----------------------- RadioRx ----------------------- */
async command error_t MacRx.prepare[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyRx.prepare();
else {
call Leds.led0On();
return FAIL;
}
}
async event void PhyRx.prepareDone()
{
signal MacRx.prepareDone[call ArbiterInfo.userId()]();
}
async command bool MacRx.isPrepared[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyRx.isPrepared();
else {
call Leds.led0On();
return FAIL;
}
}
async command error_t MacRx.receive[uint8_t client](ieee154_reftime_t *t0, uint32_t dt)
{
if (client == call ArbiterInfo.userId())
return call PhyRx.receive(t0, dt);
else {
call Leds.led0On();
return IEEE154_TRANSACTION_OVERFLOW;
}
}
event message_t* PhyRx.received(message_t *msg, ieee154_reftime_t *timestamp)
{
uint8_t *mhr = MHR(msg);
if (((mhr[1] & FC2_FRAME_VERSION_MASK) > FC2_FRAME_VERSION_1)
&& (!call RadioPromiscuousMode.get()))
return msg;
#ifndef IEEE154_SECURITY_ENABLED
if ((mhr[0] & FC1_SECURITY_ENABLED)
&& (!call RadioPromiscuousMode.get()))
return msg;
#endif
return signal MacRx.received[call ArbiterInfo.userId()](msg, timestamp);
}
async command bool MacRx.isReceiving[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyRx.isReceiving();
else {
call Leds.led0On();
return FAIL;
}
}
/* ----------------------- RadioTx ----------------------- */
async command error_t MacTx.load[uint8_t client](ieee154_txframe_t *frame)
{
if (client == call ArbiterInfo.userId())
return call PhyTx.load(frame);
else {
call Leds.led0On();
return IEEE154_TRANSACTION_OVERFLOW;
}
}
async event void PhyTx.loadDone()
{
signal MacTx.loadDone[call ArbiterInfo.userId()]();
}
async command ieee154_txframe_t* MacTx.getLoadedFrame[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyTx.getLoadedFrame();
else {
call Leds.led0On();
return NULL;
}
}
async command error_t MacTx.transmit[uint8_t client](ieee154_reftime_t *referenceTime,
uint32_t timeOffset, uint8_t numCCA, bool ackRequest)
{
if (client == call ArbiterInfo.userId())
return call PhyTx.transmit(referenceTime, timeOffset, numCCA, ackRequest);
else {
call Leds.led0On();
return IEEE154_TRANSACTION_OVERFLOW;
}
}
async event void PhyTx.transmitDone(ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
{
signal MacTx.transmitDone[call ArbiterInfo.userId()](frame, referenceTime, ackPendingFlag, error);
}
/* ----------------------- RadioOff ----------------------- */
async command error_t MacRadioOff.off[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyRadioOff.off();
else {
call Leds.led0On();
return EBUSY;
}
}
async event void PhyRadioOff.offDone()
{
signal MacRadioOff.offDone[call ArbiterInfo.userId()]();
}
async command bool MacRadioOff.isOff[uint8_t client]()
{
if (client == call ArbiterInfo.userId())
return call PhyRadioOff.isOff();
else
return EBUSY;
}
/* ----------------------- Defaults ----------------------- */
default async event void MacTx.loadDone[uint8_t client]()
{
call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_PREPARE_TX_DONE, 0, 0, 0);
}
default async event void MacTx.transmitDone[uint8_t client](ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
{
call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_TX_DONE, 0, 0, 0);
}
default async event void MacRx.prepareDone[uint8_t client]()
{
call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_PREPARE_RX_DONE, 0, 0, 0);
}
default event message_t* MacRx.received[uint8_t client](message_t *frame, ieee154_reftime_t *timestamp)
{
call Debug.log(LEVEL_INFO, RadioRxTxP_DEFAULT_RECEIVED, client, call ArbiterInfo.userId(), 0xff);
return frame;
}
default async event void MacRadioOff.offDone[uint8_t client]()
{
call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_OFFDONE, 0, 0, 0);
}
}
--- NEW FILE: FrameDispatchP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:28 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
configuration FrameDispatchP
{
provides
{
interface RadioRx as RadioRx[uint8_t client];
interface RadioTx as RadioTx[uint8_t client];
interface RadioOff as RadioOff[uint8_t client];
interface Resource as Token[uint8_t client];
interface ResourceRequested as TokenRequested[uint8_t client];
interface ResourceTransferControl as TokenTransferControl;
interface GetNow<bool> as IsResourceRequested;
interface Leds as LedsRadioClient;
} uses {
interface RadioRx as PhyRx;
interface RadioTx as PhyTx;
interface RadioOff as PhyRadioOff;
interface Get<bool> as RadioPromiscuousMode;
interface Leds;
interface Ieee802154Debug as Debug;
}
}
implementation
{
components FrameDispatchImplP;
RadioRx = FrameDispatchImplP.MacRx;
RadioTx = FrameDispatchImplP.MacTx;
RadioOff = FrameDispatchImplP.MacRadioOff;
PhyRx = FrameDispatchImplP.PhyRx;
PhyTx = FrameDispatchImplP.PhyTx;
PhyRadioOff = FrameDispatchImplP.PhyRadioOff;
RadioPromiscuousMode = FrameDispatchImplP;
Leds = FrameDispatchImplP;
Debug = FrameDispatchImplP;
LedsRadioClient = Leds;
components new SimpleRoundRobinTransferArbiterC(IEEE802154_RADIO_RESOURCE) as Arbiter;
Token = Arbiter;
TokenRequested = Arbiter;
TokenTransferControl = Arbiter;
IsResourceRequested = Arbiter;
FrameDispatchImplP.ArbiterInfo -> Arbiter;
}
--- NEW FILE: IndirectTxP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:28 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
module IndirectTxP
{
provides
{
interface Init as Reset;
interface FrameTx[uint8_t client];
interface WriteBeaconField as PendingAddrWrite;
interface Notify<bool> as PendingAddrSpecUpdated;
interface Purge;
}
uses
{
interface FrameTx as CoordCapTx;
interface FrameRx as DataRequestRx;
interface MLME_GET;
interface FrameUtility;
interface Timer<TSymbolIEEE802154> as IndirectTxTimeout;
interface TimeCalc;
interface Leds;
interface Ieee802154Debug as Debug;
}
}
implementation
{
enum {
SEND_THIS_FRAME = 0x80,
NUM_MAX_PENDING = 7,
};
ieee154_txframe_t *m_txFrameTable[NUM_MAX_PENDING];
ieee154_txframe_t *m_pendingTxFrame;
uint8_t m_client;
uint8_t m_numTableEntries;
uint8_t m_numShortPending;
uint8_t m_numExtPending;
task void tryCoordCapTxTask();
void tryCoordCapTx();
command error_t Reset.init()
{
uint8_t i;
// CAP/Queue component is always reset first, i.e. there
// should be no outstanding frames
call IndirectTxTimeout.stop();
for (i=0; i<NUM_MAX_PENDING; i++)
if (m_txFrameTable[i] != NULL)
signal FrameTx.transmitDone[m_txFrameTable[i]->client](m_txFrameTable[i], IEEE154_TRANSACTION_OVERFLOW);
for (i=0; i<NUM_MAX_PENDING; i++)
m_txFrameTable[i] = NULL; // empty slot
m_pendingTxFrame = NULL;
m_numTableEntries = 0;
m_numShortPending = 0;
m_numExtPending = 0;
return SUCCESS;
}
uint32_t getPersistenceTime()
{
uint32_t persistenceTime;
persistenceTime = call MLME_GET.macTransactionPersistenceTime();
persistenceTime *= IEEE154_aBaseSuperframeDuration;
persistenceTime *= ((uint16_t) 1) << call MLME_GET.macBeaconOrder();
return persistenceTime;
}
command ieee154_status_t Purge.purge(uint8_t msduHandle)
{
return IEEE154_INVALID_HANDLE; // TODO
}
command uint8_t PendingAddrWrite.write(uint8_t *pendingAddrField, uint8_t maxlen)
{
// write the pending addr field (inside the beacon frame)
uint8_t i, j, k=0;
uint8_t *longAdrPtr[NUM_MAX_PENDING];
nxle_uint16_t *adrPtr;
ieee154_txframe_t *txFrame;
uint8_t len = call PendingAddrWrite.getLength();
if (len > maxlen)
return 0;
pendingAddrField[0] = 0;
adrPtr = (nxle_uint16_t *) &pendingAddrField[1];
for (i=0; i<NUM_MAX_PENDING; i++){
if (!m_txFrameTable[i])
continue;
txFrame = m_txFrameTable[i];
if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT){
*adrPtr++ = *((nxle_uint16_t*) &txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]);
} else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
longAdrPtr[k++] = &(txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]);
}
for (i=0; i<m_numExtPending; i++)
for (j=0; j<8; j++)
pendingAddrField[1 + 2*m_numShortPending + i*8 + j] = longAdrPtr[i][j];
pendingAddrField[0] = m_numShortPending | (m_numExtPending << 4);
call Debug.log(LEVEL_INFO, IndirectTxP_BEACON_ASSEMBLY, len,0,0);
return len;
}
command uint8_t PendingAddrWrite.getLength()
{
return 1 + m_numShortPending * 2 + m_numExtPending * 8;
}
command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
{
// send a frame through indirect transmission
uint8_t i;
if (m_numTableEntries >= NUM_MAX_PENDING){
call Debug.log(LEVEL_IMPORTANT, IndirectTxP_OVERFLOW, 0,0,0);
return IEEE154_TRANSACTION_OVERFLOW;
}
txFrame->client = client;
txFrame->metadata->timestamp = call IndirectTxTimeout.getNow();
for (i=0; i<NUM_MAX_PENDING; i++)
if (!m_txFrameTable[i]) // there must be an empty slot
break;
m_txFrameTable[i] = txFrame;
m_numTableEntries += 1;
if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
m_numShortPending++;
else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
m_numExtPending++;
if (!call IndirectTxTimeout.isRunning())
call IndirectTxTimeout.startOneShot(getPersistenceTime());
call Debug.log(LEVEL_INFO, IndirectTxP_NOTIFIED, 0,0,0);
signal PendingAddrSpecUpdated.notify(TRUE);
return IEEE154_SUCCESS;
}
event message_t* DataRequestRx.received(message_t* frame)
{
uint8_t i, j, srcAddressMode, dstAddressMode, *src;
uint8_t *mhr = MHR(frame);
uint8_t destMode = (mhr[1] & FC2_DEST_MODE_MASK);
// received a data request frame from a device
// have we got some pending data for it ?
if (!m_numTableEntries)
return frame;
srcAddressMode = (mhr[1] & FC2_SRC_MODE_MASK);
if (!(srcAddressMode & FC2_SRC_MODE_SHORT))
return frame; // no source address
src = mhr + MHR_INDEX_ADDRESS;
if (destMode == FC2_DEST_MODE_SHORT)
src += 4;
else if (destMode == FC2_DEST_MODE_EXTENDED)
src += 10;
if (!((mhr[0] & FC1_PAN_ID_COMPRESSION) && (mhr[1] & FC2_DEST_MODE_SHORT)))
src += 2;
for (i=0; i<NUM_MAX_PENDING; i++){
if (!m_txFrameTable[i])
continue;
else {
dstAddressMode = (m_txFrameTable[i]->header->mhr[1] & FC2_DEST_MODE_MASK);
if ((dstAddressMode << 4) != srcAddressMode)
continue;
else {
// we know: dstAddressMode IN [2,3]
uint8_t *dst = &(m_txFrameTable[i]->header->mhr[MHR_INDEX_ADDRESS]) + 2;
uint8_t len = ((srcAddressMode == FC2_SRC_MODE_SHORT) ? 2 : 8);
for (j=0; j<len; j++)
if (*dst != *src)
break;
if (j==len)
break; // match! break from outer loop
}
}
}
call Debug.log(LEVEL_INFO, IndirectTxP_REQUESTED, NUM_MAX_PENDING-i,i,*src);
if (i != NUM_MAX_PENDING){
// found a matching frame, mark it for transmission
m_txFrameTable[i]->client |= SEND_THIS_FRAME;
post tryCoordCapTxTask();
} else {
// TODO: send an empty data frame to the device
}
return frame;
}
void tryCoordCapTx()
{
// iterate over the queued frames and transmit them in the CAP
// (if they are marked for transmission)
uint8_t i;
if (!m_pendingTxFrame && m_numTableEntries){
for (i=0; i<NUM_MAX_PENDING; i++)
if (m_txFrameTable[i] && (m_txFrameTable[i]->client & SEND_THIS_FRAME)){
// TODO: set frame pending bit, if there's more data for this destination
m_pendingTxFrame = m_txFrameTable[i];
m_client = m_txFrameTable[i]->client;
if (call CoordCapTx.transmit(m_txFrameTable[i]) == IEEE154_SUCCESS){
call Debug.log(LEVEL_INFO, IndirectTxP_SEND_NOW, 0,0,0);
} else {
m_pendingTxFrame = 0;
post tryCoordCapTxTask();
}
return; // done - wait for txDone
}
}
}
task void tryCoordCapTxTask()
{
tryCoordCapTx();
}
event void IndirectTxTimeout.fired()
{
// a transaction has expired
uint32_t now = call IndirectTxTimeout.getNow(), dt=0;
uint32_t persistenceTime = getPersistenceTime();
uint8_t i;
for (i=0; i<NUM_MAX_PENDING; i++)
if (m_txFrameTable[i] && m_txFrameTable[i] != m_pendingTxFrame){
if (call TimeCalc.hasExpired(m_txFrameTable[i]->metadata->timestamp, persistenceTime)){
ieee154_txframe_t *txFrame = m_txFrameTable[i];
txFrame->client &= ~SEND_THIS_FRAME;
m_txFrameTable[i] = NULL;
m_numTableEntries -= 1;
if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
m_numShortPending--;
else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
m_numExtPending--;
signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_EXPIRED);
signal PendingAddrSpecUpdated.notify(TRUE);
} else if (call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now) > dt){
dt = call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now);
}
}
if (dt != 0){
if (dt > persistenceTime)
dt = persistenceTime;
call IndirectTxTimeout.startOneShot(persistenceTime - dt);
}
}
event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
uint8_t i;
for (i=0; i<NUM_MAX_PENDING; i++)
if (m_txFrameTable[i] == txFrame){
m_txFrameTable[i] = NULL; // slot is now empty
break;
}
signal PendingAddrSpecUpdated.notify(TRUE);
m_pendingTxFrame = NULL;
txFrame->client = m_client;
txFrame->client &= ~SEND_THIS_FRAME;
m_numTableEntries -= 1;
if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
m_numShortPending--;
else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
m_numExtPending--;
signal FrameTx.transmitDone[txFrame->client](txFrame, status);
post tryCoordCapTxTask();
call Debug.log(LEVEL_INFO, IndirectTxP_SEND_DONE, status,m_numTableEntries,0);
}
command error_t PendingAddrSpecUpdated.enable(){return FAIL;}
command error_t PendingAddrSpecUpdated.disable(){return FAIL;}
default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){}
}
--- NEW FILE: PibP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
[...1025 lines suppressed...]
call FrameUtility.convertToNative(&dest, addrLE);
return dest == m_aExtendedAddressLE;
}
bool isCoordExtendedAddress(uint8_t *addrLE)
{
uint64_t dest;
call FrameUtility.convertToNative(&dest, addrLE);
return dest == m_pib.macCoordExtendedAddress;
}
command bool IsBeaconEnabledPAN.get()
{
return (m_panType == BEACON_ENABLED_PAN);
}
default event void PIBUpdate.notify[uint8_t PIBAttributeID](const void* PIBAttributeValue){}
command error_t PIBUpdate.enable[uint8_t PIBAttributeID](){return FAIL;}
command error_t PIBUpdate.disable[uint8_t PIBAttributeID](){return FAIL;}
}
--- NEW FILE: PollP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:28 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
module PollP
{
provides
{
interface Init;
interface MLME_POLL;
interface FrameRx as DataRx;
interface DataRequest as DataRequest[uint8_t client];
}
uses
{
interface FrameTx as PollTx;
interface FrameExtracted as DataExtracted;
interface FrameUtility;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface Pool<ieee154_txcontrol_t> as TxControlPool;
interface Ieee802154Debug as Debug;
interface MLME_GET;
interface Get<uint64_t> as LocalExtendedAddress;
}
}
implementation
{
enum {
HANDLE_MLME_POLL_REQUEST = 0xFF,
HANDLE_MLME_POLL_SUCCESS = 0xFE,
};
int m_numPending;
uint8_t m_dataRequestCmdID = CMD_FRAME_DATA_REQUEST;
void buildDataRequestFrame( uint8_t destAddrMode, uint16_t destPANId,
uint8_t* DstAddr, uint8_t srcAddrMode, ieee154_txframe_t *txFrame);
command error_t Init.init()
{
m_numPending = 0;
return SUCCESS;
}
command ieee154_status_t MLME_POLL.request (
uint8_t coordAddrMode,
uint16_t coordPANID,
ieee154_address_t coordAddress,
ieee154_security_t *security
)
{
ieee154_txframe_t *txFrame;
ieee154_txcontrol_t *txControl;
uint8_t srcAddrMode = 2;
ieee154_status_t txStatus = IEEE154_SUCCESS;
uint8_t coordAddressLE[8]; // little endian is what we want
if (security && security->SecurityLevel)
txStatus = IEEE154_UNSUPPORTED_SECURITY;
else if (coordAddrMode < 2 || coordAddrMode > 3 || coordPANID == 0xFFFF)
txStatus = IEEE154_INVALID_PARAMETER;
else if (!(txFrame = call TxFramePool.get()))
// none of the predefined return value really fits
txStatus = IEEE154_TRANSACTION_OVERFLOW;
else if (!(txControl = call TxControlPool.get())){
call TxFramePool.put(txFrame);
txStatus = IEEE154_TRANSACTION_OVERFLOW;
} else {
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
if (coordAddrMode == ADDR_MODE_SHORT_ADDRESS)
*((nxle_uint16_t*) &coordAddressLE) = coordAddress.shortAddress;
else
call FrameUtility.convertToLE(coordAddressLE, &coordAddress.extendedAddress);
txFrame->handle = HANDLE_MLME_POLL_REQUEST;
if (call MLME_GET.macShortAddress() >= 0xFFFE)
srcAddrMode = 3;
buildDataRequestFrame(coordAddrMode, coordPANID, coordAddressLE, srcAddrMode, txFrame);
if ((txStatus = call PollTx.transmit(txFrame)) != IEEE154_SUCCESS){
call TxFramePool.put(txFrame);
call TxControlPool.put(txControl);
call Debug.log(LEVEL_IMPORTANT, PollP_ALLOC_FAIL1, 0, 0, 0);
} else
m_numPending++;
}
return txStatus;
}
command ieee154_status_t DataRequest.poll[uint8_t client](uint8_t CoordAddrMode,
uint16_t CoordPANId, uint8_t *CoordAddressLE, uint8_t srcAddrMode)
{
ieee154_txframe_t *txFrame;
ieee154_txcontrol_t *txControl;
ieee154_status_t status = IEEE154_TRANSACTION_OVERFLOW;
call Debug.log(LEVEL_INFO, PollP_INTERNAL_POLL, CoordAddrMode, client, m_numPending);
if (client == SYNC_CLIENT && m_numPending != 0){
// no point in auto-requesting if user request is pending
signal DataRequest.pollDone[client]();
return IEEE154_SUCCESS;
} else if ((txFrame = call TxFramePool.get())){
if (!(txControl = call TxControlPool.get()))
call TxFramePool.put(txFrame);
else {
txFrame->header = &txControl->header;
txFrame->metadata = &txControl->metadata;
txFrame->handle = client;
buildDataRequestFrame(CoordAddrMode, CoordPANId,
CoordAddressLE, srcAddrMode, txFrame);
if ((status = call PollTx.transmit(txFrame)) != IEEE154_SUCCESS){
call TxControlPool.put(txControl);
call TxFramePool.put(txFrame);
call Debug.log(LEVEL_IMPORTANT, PollP_ALLOC_FAIL2, 0, 0, 0);
} else
m_numPending++;
}
}
if (status != IEEE154_SUCCESS)
signal DataRequest.pollDone[client]();
return status;
}
void buildDataRequestFrame(uint8_t destAddrMode, uint16_t destPANId,
uint8_t* destAddrPtrLE, uint8_t srcAddrMode, ieee154_txframe_t *txFrame)
{
// destAddrPtrLE points to an address in little-endian format !
ieee154_address_t srcAddress;
uint8_t *mhr;
uint16_t srcPANId;
ieee154_address_t DstAddr;
srcPANId = call MLME_GET.macPANId();
memcpy(&DstAddr, destAddrPtrLE, destAddrMode == 2 ? 2 : 8);
mhr = txFrame->header->mhr;
mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_CMD | FC1_ACK_REQUEST;
if (destAddrMode >= 2 && srcAddrMode >= 2 && destPANId == srcPANId)
mhr[MHR_INDEX_FC1] |= FC1_PAN_ID_COMPRESSION;
mhr[MHR_INDEX_FC2] = destAddrMode << FC2_DEST_MODE_OFFSET;
mhr[MHR_INDEX_FC2] |= srcAddrMode << FC2_SRC_MODE_OFFSET;
if (srcAddrMode == 2)
srcAddress.shortAddress = call MLME_GET.macShortAddress();
else
srcAddress.extendedAddress = call LocalExtendedAddress.get();
txFrame->headerLen = call FrameUtility.writeHeader(
txFrame->header->mhr,
destAddrMode,
destPANId,
&DstAddr,
srcAddrMode,
srcPANId,
&srcAddress,
(mhr[MHR_INDEX_FC1] & FC1_PAN_ID_COMPRESSION) ? TRUE: FALSE);
txFrame->payload = &m_dataRequestCmdID;
txFrame->payloadLen = 1;
}
event message_t* DataExtracted.received(message_t* frame, ieee154_txframe_t *txFrame)
{
if (!txFrame){
call Debug.log(LEVEL_CRITICAL, PollP_INTERNAL_ERROR, 0, 0, 0);
return frame;
} else
call Debug.log(LEVEL_INFO, PollP_SUCCESS, 0, 0, 0);
if (txFrame->handle == HANDLE_MLME_POLL_REQUEST)
signal MLME_POLL.confirm(IEEE154_SUCCESS);
else
signal DataRequest.pollDone[txFrame->handle]();
txFrame->handle = HANDLE_MLME_POLL_SUCCESS; // mark as processed
// TODO: check if pending bit is set (then initiate another POLL)
call Debug.log(LEVEL_IMPORTANT, PollP_RX, txFrame->handle, 0, 0);
return signal DataRx.received(frame);
}
event void PollTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
call Debug.log(LEVEL_IMPORTANT, PollP_TXDONE, status, txFrame->handle, 0);
m_numPending--;
if (txFrame->handle != HANDLE_MLME_POLL_SUCCESS){
// didn't receive a DATA frame from the coordinator
if (status == IEEE154_SUCCESS) // TODO: can this happen if a frame other than DATA was extracted?
status = IEEE154_NO_DATA;
if (txFrame->handle == HANDLE_MLME_POLL_REQUEST)
signal MLME_POLL.confirm(status);
else
signal DataRequest.pollDone[txFrame->handle]();
}
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) txFrame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(txFrame);
}
default event void MLME_POLL.confirm(ieee154_status_t status){}
default event void DataRequest.pollDone[uint8_t client](){}
}
--- NEW FILE: RadioClientC.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:28 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
generic configuration RadioClientC()
{
provides
{
interface RadioRx;
interface RadioTx;
interface RadioOff;
interface Resource as Token;
interface ResourceRequested as TokenRequested;
interface ResourceTransfer;
interface ResourceTransferred;
interface ResourceTransferConnector as TransferFrom;
interface GetNow<bool> as IsResourceRequested;
} uses {
interface ResourceTransferConnector as TransferTo;
}
}
implementation
{
enum {
CLIENT = unique(IEEE802154_RADIO_RESOURCE),
};
components FrameDispatchP;
RadioRx = FrameDispatchP.RadioRx[CLIENT];
RadioTx = FrameDispatchP.RadioTx[CLIENT];
RadioOff = FrameDispatchP.RadioOff[CLIENT];
Token = FrameDispatchP.Token[CLIENT];
IsResourceRequested = FrameDispatchP.IsResourceRequested;
TokenRequested = FrameDispatchP.TokenRequested[CLIENT];
components new TransferClientP(CLIENT);
ResourceTransfer = TransferClientP;
ResourceTransferred = TransferClientP;
TransferTo = TransferClientP;
TransferFrom = TransferClientP;
TransferClientP.ResourceTransferControl -> FrameDispatchP;
TransferClientP.Leds -> FrameDispatchP;
}
--- NEW FILE: README.txt ---
This directory contains "TKN15.4", a platform-independent IEEE 802.15.4-2006
MAC implementation. The code is still under active development, but most of the
functionality described in the standard is implemented. The MAC itself is
platform-independent, but it requires (1) a suitable radio driver, (2)
Alarms/Timers with symbol precision and (3) some "platform glue" code (defining
guard times, etc.). Currently the only supported platform is TelosB (however:
without additional hardware support the timing is not standard compliant).
Status 6/16/08
--------------
missing functionality:
- security (not planned)
- GTS (not planned)
- non-beacon-enabled mode
- PAN ID conflict resolution
- multiple indirect transmissions to the same destination
- documentation
Implementation
--------------
MAC implementation: tinyos-2.x/tos/lib/mac/tkn154
MAC interfaces: tinyos-2.x/tos/lib/mac/tkn154/interfaces
CC2420 driver: tinyos-2.x/tos/chips/cc2420_tkn154
TelosB "platform glue" code: tinyos-2.x/tos/platforms/telosb/mac/tkn154
Example applications: tinyos-2.x/apps/tests/tkn154
Copyright
---------
This work was supported by the the European Commision within the 6th Framework
Project 2005-IST-5-033406-STP (ANGEL project)
Author: Jan-Hinrich Hauer <hauer at tkn.tu-berlin.de>
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
--- NEW FILE: RxEnableP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:28 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_PHY.h"
#include "TKN154_MAC.h"
module RxEnableP
{
provides
{
interface Init;
interface MLME_RX_ENABLE;
interface SplitControl as PromiscuousMode;
interface FrameRx;
interface Get<bool> as PromiscuousModeGet;
interface GetNow<bool> as IsRxEnableActive;
interface Notify<bool> as RxEnableStateChange;
}
uses
{
interface Resource as Token;
interface RadioRx as PromiscuousRx;
interface RadioOff;
interface Set<bool> as RadioPromiscuousMode;
interface Ieee802154Debug as Debug;
interface Timer<TSymbolIEEE802154> as RxEnableTimer;
interface Get<bool> as IsBeaconEnabledPAN;
interface Get<ieee154_macPanCoordinator_t> as IsMacPanCoordinator;
interface Get<bool> as IsTrackingBeacons;
interface GetNow<uint32_t> as IncomingSfStart;
interface GetNow<uint32_t> as IncomingBeaconInterval;
interface Get<bool> as IsSendingBeacons;
interface GetNow<uint32_t> as OutgoingSfStart;
interface GetNow<uint32_t> as OutgoingBeaconInterval;
interface Notify<bool> as WasRxEnabled;
interface TimeCalc;
}
}
implementation
{
enum promiscuous_state {
S_IDLE,
S_STARTING,
S_STARTED,
S_STOPPING,
} m_promiscuousState;
uint32_t m_rxOnDuration;
uint32_t m_rxOnOffset;
uint32_t m_rxOnAnchor;
norace bool m_isRxEnabled;
bool m_isRxEnableConfirmPending;
task void prepareDoneTask();
task void radioOffDoneTask();
command error_t Init.init()
{
if (m_isRxEnableConfirmPending){
m_isRxEnableConfirmPending = FALSE;
signal MLME_RX_ENABLE.confirm(IEEE154_SUCCESS);
}
m_isRxEnabled = FALSE;
call RxEnableTimer.stop();
return SUCCESS;
}
/* ----------------------- MLME-RX-ENABLE ----------------------- */
command ieee154_status_t MLME_RX_ENABLE.request (
bool DeferPermit,
uint32_t RxOnTime,
uint32_t RxOnDuration
)
{
uint32_t lastBeaconTime=0;
uint32_t beaconInterval=0;
if (m_isRxEnableConfirmPending)
return IEEE154_TRANSACTION_OVERFLOW;
if (RxOnTime > 0xFFFFFF || RxOnDuration > 0xFFFFFF)
return IEEE154_INVALID_PARAMETER;
if (call IsBeaconEnabledPAN.get()){
if (call IsSendingBeacons.get() && call IsMacPanCoordinator.get()){
// for OUTGOING SUPERFRAME
lastBeaconTime = call OutgoingSfStart.getNow();
beaconInterval = call OutgoingBeaconInterval.getNow();
} else if (call IsTrackingBeacons.get()){
// for INCOMING SUPERFRAME
lastBeaconTime = call IncomingSfStart.getNow();
beaconInterval = call IncomingBeaconInterval.getNow();
}
if (beaconInterval == 0)
return IEEE154_PAST_TIME; // we're not even sending/receiving beacons
if (RxOnTime+RxOnDuration >= beaconInterval)
return IEEE154_ON_TIME_TOO_LONG;
if (call TimeCalc.hasExpired(lastBeaconTime, RxOnTime - IEEE154_aTurnaroundTime)){
if (!DeferPermit)
return IEEE154_PAST_TIME;
else {
// defer to next beacon
RxOnTime += beaconInterval;
}
}
m_rxOnAnchor = lastBeaconTime;
m_rxOnOffset = RxOnTime;
} else {
m_rxOnAnchor = call RxEnableTimer.getNow();
m_rxOnOffset = 0;
}
m_rxOnDuration = RxOnDuration;
m_isRxEnabled = FALSE;
m_isRxEnableConfirmPending = TRUE;
call RxEnableTimer.startOneShotAt(m_rxOnAnchor, m_rxOnOffset);
signal RxEnableStateChange.notify(TRUE);
return IEEE154_SUCCESS;
}
event void RxEnableTimer.fired()
{
if (!m_isRxEnabled){
m_isRxEnabled = TRUE;
call RxEnableTimer.startOneShotAt(m_rxOnAnchor, m_rxOnOffset + m_rxOnDuration);
} else {
m_isRxEnabled = FALSE;
if (m_isRxEnableConfirmPending){
// this means we tried to enable rx, but never
// succeeded, because there were "other
// responsibilities" - but is SUCCESS really
// an appropriate error code in this case?
m_isRxEnableConfirmPending = FALSE;
signal MLME_RX_ENABLE.confirm(IEEE154_SUCCESS);
}
}
signal RxEnableStateChange.notify(TRUE);
}
async command bool IsRxEnableActive.getNow()
{
return m_isRxEnabled;
}
event void WasRxEnabled.notify( bool val )
{
if (m_isRxEnabled && m_isRxEnableConfirmPending){
m_isRxEnableConfirmPending = FALSE;
signal MLME_RX_ENABLE.confirm(IEEE154_SUCCESS);
}
}
command error_t RxEnableStateChange.enable(){return FAIL;}
command error_t RxEnableStateChange.disable(){return FAIL;}
/* ----------------------- Promiscuous Mode ----------------------- */
command bool PromiscuousModeGet.get()
{
return (m_promiscuousState == S_STARTED);
}
command error_t PromiscuousMode.start()
{
if (m_promiscuousState != S_IDLE)
return FAIL;
m_promiscuousState = S_STARTING;
call Token.request();
call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_REQUEST, m_promiscuousState, 0, 0);
call Debug.flush();
return SUCCESS;
}
event void Token.granted()
{
if (m_promiscuousState != S_STARTING){
call Token.release();
return;
}
call RadioPromiscuousMode.set(TRUE);
if (call PromiscuousRx.prepare() != IEEE154_SUCCESS){
m_promiscuousState = S_IDLE;
call Token.release();
call Debug.log(LEVEL_IMPORTANT, EnableRxP_RADIORX_ERROR, 0, 0, 0);
signal PromiscuousMode.startDone(FAIL);
}
}
async event void PromiscuousRx.prepareDone()
{
post prepareDoneTask();
}
task void prepareDoneTask()
{
if (m_promiscuousState != S_STARTING){
call Token.release();
return;
}
m_promiscuousState = S_STARTED;
call PromiscuousRx.receive(NULL, 0);
signal PromiscuousMode.startDone(SUCCESS);
call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_ON, m_promiscuousState, 0, 0);
}
event message_t* PromiscuousRx.received(message_t *frame, ieee154_reftime_t *timestamp)
{
if (m_promiscuousState == S_STARTED){
((ieee154_header_t*) frame->header)->length |= FRAMECTL_PROMISCUOUS;
return signal FrameRx.received(frame);
} else
return frame;
}
command error_t PromiscuousMode.stop()
{
if (m_promiscuousState != S_STARTED)
return FAIL;
m_promiscuousState = S_STOPPING;
call RadioOff.off();
return SUCCESS;
}
async event void RadioOff.offDone()
{
post radioOffDoneTask();
}
task void radioOffDoneTask()
{
if (m_promiscuousState != S_STOPPING){
call Token.release();
return;
}
m_promiscuousState = S_IDLE;
call RadioPromiscuousMode.set(FALSE);
call Token.release();
signal PromiscuousMode.stopDone(SUCCESS);
call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_OFF, m_promiscuousState, 0, 0);
}
default event void PromiscuousMode.startDone(error_t error){}
default event void PromiscuousMode.stopDone(error_t error){}
default event void MLME_RX_ENABLE.confirm(ieee154_status_t status){}
}
--- NEW FILE: ScanP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
module ScanP
{
provides
{
interface Init;
interface MLME_SCAN;
interface MLME_BEACON_NOTIFY;
}
uses
{
interface MLME_GET;
interface MLME_SET;
interface EnergyDetection;
interface RadioOff;
interface RadioRx;
interface RadioTx;
interface IEEE154Frame as Frame;
interface IEEE154BeaconFrame as BeaconFrame;
interface Timer<TSymbolIEEE802154> as ScanTimer;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface Pool<ieee154_txcontrol_t> as TxControlPool;
interface Resource as Token;
interface FrameUtility;
interface Leds;
}
}
implementation
{
enum {
MAX_PAYLOAD_SIZE = 1,
};
ieee154_txframe_t *m_txFrame = NULL;
uint8_t m_payload[MAX_PAYLOAD_SIZE];
uint8_t m_scanType;
uint32_t m_scanChannels;
uint32_t m_unscannedChannels;
ieee154_macAutoRequest_t m_macAutoRequest;
norace uint32_t m_currentChannelBit;
norace uint8_t m_currentChannelNum;
void* m_resultList;
uint8_t m_resultListNumEntries;
uint8_t m_resultIndex;
ieee154_macPANId_t m_PANID;
norace uint32_t m_scanDuration;
bool m_busy = FALSE;
void nextIteration();
task void startTimerTask();
task void nextIterationTask();
command error_t Init.init()
{
// triggered by MLME_RESET; remember: Init will not be called
// while this component owns the Token, so the worst case is
// that a MLME_SCAN was accepted (returned IEEE154_SUCCESS)
// but the Token.granted() has not been signalled
if (m_busy){
m_currentChannelNum = 27;
nextIteration(); // signals confirm and resets state
}
return SUCCESS;
}
/* ----------------------- MLME-SCAN ----------------------- */
/* "The MLME-SCAN.request primitive is used to initiate a channel scan over a
* given list of channels. A device can use a channel scan to measure the
* energy on the channel, search for the coordinator with which it associated,
* or search for all coordinators transmitting beacon frames within the POS of
* the scanning device." (IEEE 802.15.4-2006 Sect. 7.1.11.1)
**/
command ieee154_status_t MLME_SCAN.request (
uint8_t ScanType,
uint32_t ScanChannels,
uint8_t ScanDuration,
uint8_t ChannelPage,
uint8_t EnergyDetectListNumEntries,
int8_t* EnergyDetectList,
uint8_t PANDescriptorListNumEntries,
ieee154_PANDescriptor_t* PANDescriptorList,
ieee154_security_t *security
)
{
ieee154_status_t status = IEEE154_SUCCESS;
ieee154_phyChannelsSupported_t supportedChannels = call MLME_GET.phyChannelsSupported();
ieee154_txcontrol_t *txControl = NULL;
if (m_busy){
status = IEEE154_SCAN_IN_PROGRESS;
} else if (security && security->SecurityLevel){
status = IEEE154_UNSUPPORTED_SECURITY;
} if ( (ScanType > 3) || (ScanType < 3 && ScanDuration > 14) ||
(ChannelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
!(supportedChannels & ScanChannels) ||
(EnergyDetectListNumEntries && PANDescriptorListNumEntries) ||
(EnergyDetectList != NULL && PANDescriptorList != NULL) ||
(EnergyDetectListNumEntries && EnergyDetectList == NULL) ||
(PANDescriptorListNumEntries && PANDescriptorList == NULL)) {
status = IEEE154_INVALID_PARAMETER;
} else if (ScanType != ENERGY_DETECTION_SCAN &&
!(m_txFrame = call TxFramePool.get())) {
status = IEEE154_TRANSACTION_OVERFLOW;
} else if (ScanType != ENERGY_DETECTION_SCAN &&
!(txControl = call TxControlPool.get())) {
call TxFramePool.put(m_txFrame);
m_txFrame = NULL;
status = IEEE154_TRANSACTION_OVERFLOW;
} else {
m_txFrame->header = &txControl->header;
m_txFrame->payload = m_payload;
m_txFrame->metadata = &txControl->metadata;
m_busy = TRUE;
m_scanType = ScanType;
m_scanChannels = ScanChannels;
m_scanDuration = (((uint32_t) 1 << ScanDuration) + 1) * IEEE154_aBaseSuperframeDuration;
m_macAutoRequest = call MLME_GET.macAutoRequest();
m_PANID = call MLME_GET.macPANId();
m_unscannedChannels = 0;
m_currentChannelBit = 1;
m_currentChannelNum = 0;
m_resultIndex = 0;
if (ScanType == ENERGY_DETECTION_SCAN){
m_resultList = EnergyDetectList;
m_resultListNumEntries = EnergyDetectListNumEntries;
} else {
m_resultList = PANDescriptorList;
m_resultListNumEntries = PANDescriptorListNumEntries;
}
if (m_resultList == NULL)
m_resultListNumEntries = 0;
call Token.request();
}
return status;
}
event void Token.granted()
{
uint8_t i;
ieee154_macPANId_t bcastPANID = 0xFFFF;
ieee154_macDSN_t dsn = call MLME_GET.macDSN();
if (!m_busy){
call Token.release();
return;
}
switch (m_scanType){
case ACTIVE_SCAN:
// beacon request frame
m_txFrame->header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_CMD;
m_txFrame->header->mhr[MHR_INDEX_FC2] = FC2_DEST_MODE_SHORT;
m_txFrame->header->mhr[MHR_INDEX_SEQNO] = dsn;
call MLME_SET.macDSN(dsn+1);
for (i=0; i<4; i++) // broadcast dest PAN ID + broadcast dest addr
m_txFrame->header->mhr[MHR_INDEX_ADDRESS + i] = 0xFF;
m_txFrame->headerLen = 7;
m_payload[0] = CMD_FRAME_BEACON_REQUEST;
m_txFrame->payloadLen = 1;
// fall through
case PASSIVE_SCAN:
call MLME_SET.macPANId(bcastPANID);
break;
case ORPHAN_SCAN:
// orphan notification frame
m_scanDuration = call MLME_GET.macResponseWaitTime();
m_txFrame->header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_CMD | FC1_PAN_ID_COMPRESSION;
m_txFrame->header->mhr[MHR_INDEX_FC2] = FC2_SRC_MODE_EXTENDED | FC2_DEST_MODE_SHORT;
m_txFrame->header->mhr[MHR_INDEX_SEQNO] = dsn;
call MLME_SET.macDSN(dsn+1);
for (i=0; i<4; i++) // broadcast dest PAN ID + broadcast dest addr
m_txFrame->header->mhr[MHR_INDEX_ADDRESS + i] = 0xFF;
call FrameUtility.copyLocalExtendedAddressLE((uint8_t*) &(m_txFrame->header[MHR_INDEX_ADDRESS + i]));
m_txFrame->headerLen = 15;
m_payload[0] = CMD_FRAME_ORPHAN_NOTIFICATION;
m_txFrame->payloadLen = 1;
break;
}
nextIteration();
}
void nextIteration()
{
error_t radioStatus = SUCCESS;
uint32_t supportedChannels = IEEE154_SUPPORTED_CHANNELS;
atomic {
while (!(m_scanChannels & m_currentChannelBit & supportedChannels) && m_currentChannelNum < 27){
m_unscannedChannels |= m_currentChannelBit;
m_currentChannelBit <<= 1;
m_currentChannelNum++;
}
}
if (m_currentChannelNum < 27) {
call MLME_SET.phyCurrentChannel(m_currentChannelNum);
switch (m_scanType){
case PASSIVE_SCAN:
radioStatus = call RadioRx.prepare();
break;
case ACTIVE_SCAN:
case ORPHAN_SCAN:
radioStatus = call RadioTx.load(m_txFrame);
break;
case ENERGY_DETECTION_SCAN:
radioStatus = call EnergyDetection.start(m_scanDuration);
break;
}
if (radioStatus != SUCCESS){
call Leds.led0On();
}
} else {
ieee154_status_t result = IEEE154_SUCCESS;
// we're done
m_currentChannelBit <<= 1;
while (m_currentChannelBit){
m_unscannedChannels |= m_currentChannelBit;
m_currentChannelBit <<= 1;
}
m_unscannedChannels &= m_scanChannels; // only channels that were requested
if (m_scanType != ENERGY_DETECTION_SCAN && !m_resultIndex)
result = IEEE154_NO_BEACON;
if (m_scanType == PASSIVE_SCAN || m_scanType == ACTIVE_SCAN)
call MLME_SET.macPANId(m_PANID);
if (m_txFrame != NULL){
call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) m_txFrame->header - offsetof(ieee154_txcontrol_t, header)));
call TxFramePool.put(m_txFrame);
}
m_txFrame = NULL;
if (call Token.isOwner())
call Token.release();
m_busy = FALSE;
signal MLME_SCAN.confirm (
result,
m_scanType,
IEEE154_SUPPORTED_CHANNELPAGE,
m_unscannedChannels,
(m_scanType == ENERGY_DETECTION_SCAN) ? m_resultIndex : 0,
(m_scanType == ENERGY_DETECTION_SCAN) ? (uint8_t*) m_resultList : NULL,
((m_scanType == ACTIVE_SCAN ||
m_scanType == PASSIVE_SCAN) && m_macAutoRequest) ? m_resultIndex : 0,
((m_scanType == ACTIVE_SCAN ||
m_scanType == PASSIVE_SCAN) && m_macAutoRequest) ? (ieee154_PANDescriptor_t*) m_resultList : NULL
);
}
}
/* ----------------------- EnergyDetection ----------------------- */
event void EnergyDetection.done(error_t status, int8_t EnergyLevel)
{
if (status == SUCCESS && m_resultListNumEntries)
((uint8_t*) m_resultList)[m_resultIndex++] = EnergyLevel;
else
m_unscannedChannels |= m_currentChannelBit;
if (m_resultIndex == m_resultListNumEntries)
m_currentChannelNum = 27; // done
else
m_currentChannelNum++;
call RadioOff.off();
}
/* ----------------------- Active/Orphan scan ----------------------- */
async event void RadioTx.loadDone()
{
call RadioTx.transmit(0, 0, 0, FALSE);
}
async event void RadioTx.transmitDone(ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
{
if (call RadioRx.prepare() != SUCCESS) // must succeed
call Leds.led0On();
}
/* -------- Receive events (for Active/Passive/Orphan scan) -------- */
async event void RadioRx.prepareDone()
{
call RadioRx.receive(NULL, 0);
post startTimerTask();
}
event message_t* RadioRx.received(message_t *frame, ieee154_reftime_t *timestamp)
{
atomic {
if (!m_busy)
return frame;
if (m_scanType == ORPHAN_SCAN){
if (!m_resultIndex)
if ((MHR(frame)[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD &&
((uint8_t*)call Frame.getPayload(frame))[0] == CMD_FRAME_COORDINATOR_REALIGNMENT){
m_resultIndex++;
m_currentChannelNum = 27; // terminate scan
call RadioOff.off();
}
} else if ((((ieee154_header_t*) frame->header)->mhr[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_BEACON) {
// PASSIVE_SCAN / ACTIVE_SCAN
if (!m_macAutoRequest)
return signal MLME_BEACON_NOTIFY.indication (frame);
else if (m_resultListNumEntries && m_resultIndex < m_resultListNumEntries &&
call BeaconFrame.parsePANDescriptor(
frame,
m_currentChannelNum,
IEEE154_SUPPORTED_CHANNELPAGE,
&((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex]) == SUCCESS){
// check uniqueness: both PAN ID and source address must not be in a previously received beacon
uint8_t i;
if (m_resultIndex)
for (i=0; i<m_resultIndex; i++)
if ( ((ieee154_PANDescriptor_t*) m_resultList)[i].CoordPANId ==
((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex].CoordPANId &&
((ieee154_PANDescriptor_t*) m_resultList)[i].CoordAddrMode ==
((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex].CoordAddrMode)
if ( (((ieee154_PANDescriptor_t*) m_resultList)[i].CoordAddrMode == ADDR_MODE_SHORT_ADDRESS &&
((ieee154_PANDescriptor_t*) m_resultList)[i].CoordAddress.shortAddress ==
((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex].CoordAddress.shortAddress) ||
(((ieee154_PANDescriptor_t*) m_resultList)[i].CoordAddrMode == ADDR_MODE_EXTENDED_ADDRESS &&
((ieee154_PANDescriptor_t*) m_resultList)[i].CoordAddress.extendedAddress ==
((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex].CoordAddress.extendedAddress) )
return frame; // not unique
m_resultIndex++;
if (m_resultIndex == m_resultListNumEntries){
m_currentChannelNum = 27; // terminate scan
call RadioOff.off();
}
}
}
}
return frame;
}
/* ----------------------- Common ----------------------- */
task void startTimerTask()
{
call ScanTimer.startOneShot(m_scanDuration);
}
event void ScanTimer.fired()
{
call RadioOff.off();
}
async event void RadioOff.offDone()
{
m_currentChannelBit <<= 1;
m_currentChannelNum++;
post nextIterationTask();
}
task void nextIterationTask()
{
nextIteration();
}
default event message_t* MLME_BEACON_NOTIFY.indication ( message_t *beaconFrame ){return beaconFrame;}
default event void MLME_SCAN.confirm (
ieee154_status_t status,
uint8_t ScanType,
uint8_t ChannelPage,
uint32_t UnscannedChannels,
uint8_t EnergyDetectListNumEntries,
int8_t* EnergyDetectList,
uint8_t PANDescriptorListNumEntries,
ieee154_PANDescriptor_t* PANDescriptorList
){}
}
--- NEW FILE: SimpleRoundRobinTransferArbiterC.nc ---
/*
* "Copyright (c) 2005 Washington University in St. Louis.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY
* FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
* OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON
* UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
* MODIFICATIONS."
*/
/*
* Copyright (c) 2004, Technische Universitat Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitat Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Please refer to TEP 108 for more information about this component and its
* intended use.<br><br>
*
* This component provides the Resource, ArbiterInfo, and Resource
* Controller interfaces and uses the ResourceConfigure interface as
* described in TEP 108. It provides arbitration to a shared resource in
* an FCFS fashion. An array is used to keep track of which users have put
* in requests for the resource. Upon the release of the resource by one
* of these users, the array is checked and the next user (in FCFS order)
* that has a pending request will ge granted control of the resource. If
* there are no pending requests, then the resource becomes idle and any
* user can put in a request and immediately receive access to the
* Resource.
*
* @param <b>resourceName</b> -- The name of the Resource being shared
*
* @author Kevin Klues (klues at tkn.tu-berlin.de)
* @author Philip Levis
*/
generic configuration SimpleRoundRobinTransferArbiterC(char resourceName[]) {
provides {
interface Resource[uint8_t id];
interface ResourceRequested[uint8_t id];
interface ResourceTransferControl;
interface ArbiterInfo;
interface GetNow<bool> as IsResourceRequested;
}
uses interface ResourceConfigure[uint8_t id];
}
implementation {
components MainC;
components new RoundRobinResourceQueueC(uniqueCount(resourceName)) as Queue;
components new SimpleTransferArbiterP() as Arbiter;
MainC.SoftwareInit -> Queue;
Resource = Arbiter;
ResourceRequested = Arbiter;
ArbiterInfo = Arbiter;
ResourceConfigure = Arbiter;
ResourceTransferControl = Arbiter;
IsResourceRequested = Arbiter;
Arbiter.Queue -> Queue;
}
--- NEW FILE: SimpleTransferArbiterP.nc ---
/*
* Copyright (c) 2004, Technische Universitat Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitat Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Please refer to TEP 108 for more information about this component and its
* intended use.<br><br>
*
* This component provides the Resource, ArbiterInfo, and ResourceRequested
* interfaces and uses the ResourceConfigure interface as
* described in TEP 108. It provides arbitration to a shared resource.
* An queue is used to keep track of which users have put
* in requests for the resource. Upon the release of the resource by one
* of these users, the queue is checked and the next user
* that has a pending request will ge granted control of the resource. If
* there are no pending requests, then the resource becomes idle and any
* user can put in a request and immediately receive access to the
* Resource.
*
* @author Kevin Klues (klues at tkn.tu-berlin.de)
* @author Philip Levis
* @author: Jan Hauer <hauer at tkn.tu-berlin.de> (added resource transfer)
*/
generic module SimpleTransferArbiterP() {
provides {
interface Resource[uint8_t id];
interface ResourceRequested[uint8_t id];
interface ResourceTransferControl;
interface ArbiterInfo;
interface GetNow<bool> as IsResourceRequested;
}
uses {
interface ResourceConfigure[uint8_t id];
interface ResourceQueue as Queue;
}
}
implementation {
enum {RES_IDLE = 0, RES_GRANTING = 1, RES_BUSY = 2};
enum {NO_RES = 0xFF};
uint8_t state = RES_IDLE;
norace uint8_t resId = NO_RES;
norace uint8_t reqResId;
norace uint8_t numTransfers;
norace bool reqWhileTransferred;
task void grantedTask();
task void checkResourceRequestedTask();
async command error_t Resource.request[uint8_t id]() {
signal ResourceRequested.requested[resId]();
atomic {
if (numTransfers > 0)
reqWhileTransferred = TRUE;
if(state == RES_IDLE) {
state = RES_GRANTING;
reqResId = id;
post grantedTask();
return SUCCESS;
}
return call Queue.enqueue(id);
}
}
async command error_t Resource.immediateRequest[uint8_t id]() {
signal ResourceRequested.immediateRequested[resId]();
atomic {
if(state == RES_IDLE) {
state = RES_BUSY;
resId = id;
call ResourceConfigure.configure[resId]();
return SUCCESS;
}
return FAIL;
}
}
async command error_t Resource.release[uint8_t id]() {
bool released = FALSE;
atomic {
if(state == RES_BUSY && resId == id) {
numTransfers = 0;
reqWhileTransferred = FALSE;
if(call Queue.isEmpty() == FALSE) {
reqResId = call Queue.dequeue();
state = RES_GRANTING;
post grantedTask();
}
else {
resId = NO_RES;
state = RES_IDLE;
}
released = TRUE;
}
}
if(released == TRUE) {
call ResourceConfigure.unconfigure[id]();
return SUCCESS;
}
return FAIL;
}
async command bool IsResourceRequested.getNow()
{
return reqWhileTransferred;
}
task void checkResourceRequestedTask()
{
if (numTransfers && reqWhileTransferred)
signal ResourceRequested.requested[resId]();
}
async command error_t ResourceTransferControl.transfer(uint8_t fromClient, uint8_t toClient)
{
atomic {
if (call ArbiterInfo.userId() == fromClient){
numTransfers += 1;
call ResourceConfigure.unconfigure[fromClient]();
call ResourceConfigure.configure[resId]();
resId = toClient;
post checkResourceRequestedTask();
return SUCCESS;
}
}
return FAIL;
}
async command error_t ResourceTransferControl.release(uint8_t client)
{
return call Resource.release[client]();
}
/**
Check if the Resource is currently in use
*/
async command bool ArbiterInfo.inUse() {
atomic {
if (state == RES_IDLE)
return FALSE;
}
return TRUE;
}
/**
Returns the current user of the Resource.
If there is no current user, the return value
will be 0xFF
*/
async command uint8_t ArbiterInfo.userId() {
atomic {
if(state != RES_BUSY)
return NO_RES;
return resId;
}
}
/**
* Returns whether you are the current owner of the resource or not
*/
async command uint8_t Resource.isOwner[uint8_t id]() {
atomic {
if(resId == id && state == RES_BUSY) return TRUE;
else return FALSE;
}
}
task void grantedTask() {
atomic {
resId = reqResId;
state = RES_BUSY;
}
call ResourceConfigure.configure[resId]();
signal Resource.granted[resId]();
}
//Default event/command handlers
default event void Resource.granted[uint8_t id]() {
}
default async event void ResourceRequested.requested[uint8_t id]() {
}
default async event void ResourceRequested.immediateRequested[uint8_t id]() {
}
default async command void ResourceConfigure.configure[uint8_t id]() {
}
default async command void ResourceConfigure.unconfigure[uint8_t id]() {
}
}
--- NEW FILE: TKN154_DEBUG.h ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#ifndef __TKN154_DEBUG_H
#define __TKN154_DEBUG_H
#define LEVEL_INFO 0
#define LEVEL_IMPORTANT 50
#define LEVEL_CRITICAL 100
#define RadioRxTxP_ACQUIRED 0
#define RadioRxTxP_NOT_ACQUIRED 1
#define RadioRxTxP_TRANSFERRED 2
#define RadioRxTxP_NOT_TRANSFERRED 3
#define RadioRxTxP_RELEASED 4
#define RadioRxTxP_NOT_RELEASED 5
#define RadioRxTxP_TRANSFER_REQUEST 6
#define RadioRxTxP_DEFAULT_PREPARE_TX_DONE 7
#define RadioRxTxP_DEFAULT_TX_DONE 8
#define RadioRxTxP_DEFAULT_PREPARE_RX_DONE 9
#define RadioRxTxP_DEFAULT_RECEIVED 10
#define RadioRxTxP_DEFAULT_OFFDONE 11
#define RadioRxTxP_DEFAULT_TRANSFERRED 12
#define RadioRxTxP_DEFAULT_TRANSFERREQUEST 13
#define RadioRxTxP_ASK_ISOWNER 14
#define RadioRxTxP_RX_NOOWNER 15
#define RadioRxTxP_DEFAULT_CANCEL_TX_DONE 16
#define RadioRxTxP_DEFAULT_CANCEL_RX_DONE 17
#define SyncP_BEACON_MISSED_1 0
#define SyncP_BEACON_MISSED_2 1
#define SyncP_BEACON_MISSED_3 2
#define SyncP_TRACK_ALARM 3
#define SyncP_INVALID_PARAM 4
#define SyncP_RX_ON 5
#define SyncP_INTERNAL_ERROR 6
#define SyncP_BEACON_RX 7
#define SyncP_RADIO_BUSY 8
#define SyncP_LOST_SYNC 9
#define SyncP_RX_PACKET 10
#define SyncP_NEXT_RX_TIME 11
#define SyncP_SWITCHOFF 12
#define SyncP_RX_GARBAGE 13
#define SyncP_GOT_RESOURCE 14
#define SyncP_RELEASE_RESOURCE 15
#define SyncP_RESOURCE_REQUEST 16
#define SyncP_TRANSFER_RESOURCE 17
#define SyncP_PREPARE_RX 18
#define SyncP_REQUEST 19
#define SyncP_UPDATING 20
#define SyncP_PREPARE_RX_DONE 21
#define SyncP_INVALID_TIMESTAMP 22
#define SyncP_RX_BEACON SyncP_RX_PACKET
#define StartP_BEACON_TRANSMITTED 0
#define StartP_UPDATE_STATE 1
#define StartP_REQUEST 2
#define StartP_OWNER_TOO_FAST 3
#define StartP_BEACON_UPDATE 4
#define StartP_BEACON_UPDATE_2 5
#define StartP_PREPARE_TX 6
#define StartP_PREPARE_TXDONE 7
#define StartP_SKIPPED_BEACON 8
#define StartP_GOT_RESOURCE 9
#define StartP_TRANSMIT 10
#define PollP_ALLOC_FAIL1 0
#define PollP_ALLOC_FAIL2 1
#define PollP_INTERNAL_POLL 2
#define PollP_SUCCESS 3
#define PollP_TXDONE 4
#define PollP_WRONG_FORMAT 5
#define PollP_INTERNAL_ERROR 6
#define PollP_RX 7
#define IndirectTxP_OVERFLOW 0
#define IndirectTxP_NOTIFIED 1
#define IndirectTxP_REQUESTED 2
#define IndirectTxP_BUSY 3
#define IndirectTxP_DATA_REQUEST 4
#define IndirectTxP_SEND_NOW 5
#define IndirectTxP_SEND_NOW_FAIL 6
#define IndirectTxP_SEND_DONE 7
#define IndirectTxP_BEACON_ASSEMBLY 8
#define EnableRxP_RADIORX_ERROR 0
#define EnableRxP_PROMISCUOUS_REQUEST 1
#define EnableRxP_PROMISCUOUS_ON 2
#define EnableRxP_PROMISCUOUS_OFF 3
#define AssociateP_REQUEST 0
#define AssociateP_TXDONE 1
#define AssociateP_TIMEOUT 2
#define AssociateP_RX 3
#define AssociateP_SETTIMER 4
#define AssociateP_POLL_DONE 5
#define DISSASSOCIATE_REQUEST 50
#define DISSASSOCIATE_TXDONE 51
#define DISSASSOCIATE_RX 52
#define CapP_TOO_SHORT 0
#define CapP_SET_CAP_END 1
#define CapP_CAP_END_FIRED 2
#define DeviceCapTransmitP_CONTINUE 0
#define DeviceCapTransmitP_TOVERFLOW 1
#define DeviceCapTransmitP_RADIO_RESERVE 2
#define DeviceCapTransmitP_CCA_FAIL 3
#define DeviceCapTransmitP_NO_ACK 4
#define DeviceCapTransmitP_TX_DONE 5
#define DeviceCapTransmitP_TX_PREPARE 6
#define DeviceCapTransmitP_TX_NOW 7
#define DeviceCapTransmitP_TX_CANCEL 8
#define DeviceCapTransmitP_TX_PREPARE_DONE 9
#define DeviceCapTransmitP_CAP_END_ALARM 10
#define DeviceCapTransmitP_RADIO_OFF 11
#define DeviceCapTransmitP_RADIO_RX 12
#define DeviceCapTransmitP_TX_CANCEL_DONE 13
#define DeviceCapTransmitP_TX_DONE_UNKNOWN 14
#define DeviceCapTransmitP_RESOURCE_REQ 15
#define DeviceCapTransmitP_GOT_RESOURCE 16
#define CoordCapTransmitP_RADIO_RESERVE 0
#define CoordCapTransmitP_TX_CANCEL 1
#define CoordCapTransmitP_CCA_FAIL 2
#define CoordCapTransmitP_CAP_END_ALARM 3
#define CoordCapTransmitP_OFF_DONE 4
#define CoordCapTransmitP_FINISH_TX 5
#define CoordCapTransmitP_RADIO_RX 6
#define Phy_RX_CANCEL 0
#define Phy_RX_NOW 1
#define Phy_LOAD_TX_FIFO 2
#define Phy_LOAD_TX_FIFO_DONE 3
#define Phy_LOAD_TX_CANCEL 4
#define Phy_LOAD_TX_NOW 5
#define Phy_LOAD_TX_RX_NOW 6
#define Phy_SEND_DONE 7
#define Phy_SPI_GRANTED 8
#define Phy_RADIO_OFF 9
#define Phy_RADIO_OFF_DONE 10
#define Phy_RADIO_PREPARE_RX 11
#define Phy_RADIO_PREPARE_TX 12
#define Phy_RADIO_TX_DONE 13
#define Phy_RADIO_RECEIVED 14
#define PhyRx_START 0
#define PhyRx_STOP 1
#define PhyRx_FIFOP 2
#define PhyRx_RXON 3
enum {
// IDs assigned for debugging
START_CLIENT = 0,
COORD_CAP_CLIENT = 1,
COORD_CFP_CLIENT = 2,
SYNC_CLIENT = 3,
DEVICE_CAP_CLIENT = 4,
DEVICE_CFP_CLIENT = 5,
SCAN_CLIENT = 6,
RADIORXTX_CLIENT = 7,
PIBDATABASE_CLIENT = 8,
ASSOCIATE_CLIENT = 9,
DEVICECAPQUEUE_CLIENT = 10,
INDIRECTTX_DEBUG_CLIENT = 11,
DATA_CLIENT = 12,
POLL_CLIENT = 13,
DISASSOCIATE_CLIENT = 14,
RXENABLE_CLIENT = 15,
PHY_CLIENT = 16,
PHY_TXCLIENT = 17,
PHY_RXCLIENT = 18,
};
typedef nx_struct serial_debug_msg {
nx_uint8_t client;
nx_uint8_t eventID;
nx_uint8_t seqno;
nx_uint8_t priority;
nx_uint32_t timestamp;
nx_uint32_t param1;
nx_uint32_t param2;
nx_uint32_t param3;
} serial_debug_msg_t;
#ifndef SERIAL_DBG_MSGBUF_SIZE
#define SERIAL_DBG_MSGBUF_SIZE 25
#endif
enum {
AM_SERIAL_DEBUG_MSG = 222,
};
#endif // __TKN154_DEBUG_H
--- NEW FILE: TKN154.h ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#ifndef __TKN154_H
#define __TKN154_H
/****************************************************
* IEEE 802.15.4 Enumerations
*/
typedef enum ieee154_status
{
IEEE154_SUCCESS = 0x00,
IEEE154_BEACON_LOSS = 0xE0,
IEEE154_CHANNEL_ACCESS_FAILURE = 0xE1,
IEEE154_COUNTER_ERROR = 0xDB,
IEEE154_DENIED = 0xE2,
IEEE154_DISABLE_TRX_FAILURE = 0xE3,
IEEE154_FRAME_TOO_LONG = 0xE5,
IEEE154_IMPROPER_KEY_TYPE = 0xDC,
IEEE154_IMPROPER_SECURITY_LEVEL = 0xDD,
IEEE154_INVALID_ADDRESS = 0xF5,
IEEE154_INVALID_GTS = 0xE6,
IEEE154_INVALID_HANDLE = 0xE7,
IEEE154_INVALID_INDEX = 0xF9,
IEEE154_INVALID_PARAMETER = 0xE8,
IEEE154_LIMIT_REACHED = 0xFA,
IEEE154_NO_ACK = 0xE9,
IEEE154_NO_BEACON = 0xEA,
IEEE154_NO_DATA = 0xEB,
IEEE154_NO_SHORT_ADDRESS = 0xEC,
IEEE154_ON_TIME_TOO_LONG = 0xF6,
IEEE154_OUT_OF_CAP = 0xED,
IEEE154_PAN_ID_CONFLICT = 0xEE,
IEEE154_PAST_TIME = 0xF7,
IEEE154_READ_ONLY = 0xFB,
IEEE154_REALIGNMENT = 0xEF,
IEEE154_SCAN_IN_PROGRESS = 0xFC,
IEEE154_SECURITY_ERROR = 0xE4, //FAILED_SECURITY_CHECK = 0xE4 //802.15.4_2003
IEEE154_SUPERFRAME_OVERLAP = 0xFD,
IEEE154_TRACKING_OFF = 0xF8,
IEEE154_TRANSACTION_EXPIRED = 0xF0,
IEEE154_TRANSACTION_OVERFLOW = 0xF1,
IEEE154_TX_ACTIVE = 0xF2,
IEEE154_UNAVAILABLE_KEY = 0xF3,
IEEE154_UNSUPPORTED_ATTRIBUTE = 0xF4,
IEEE154_UNSUPPORTED_LEGACY = 0xDE,
IEEE154_UNSUPPORTED_SECURITY = 0xDF,
} ieee154_status_t;
typedef enum ieee154_association_status
{
IEEE154_ASSOCIATION_SUCCESSFUL = 0x00,
IEEE154_PAN_AT_CAPACITY = 0x01,
IEEE154_ACCESS_DENIED = 0x02
} ieee154_association_status_t;
typedef enum ieee154_disassociation_reason
{
IEEE154_COORDINATOR_WISHES_DEVICE_TO_LEAVE = 0x01,
IEEE154_DEVICE_WISHES_TO_LEAVE = 0x02
} ieee154_disassociation_reason_t;
typedef union ieee154_address {
// Whether this is a short or extended address
// depends on the respective addressing mode
uint16_t shortAddress;
uint64_t extendedAddress;
} ieee154_address_t;
typedef struct ieee154_security {
// Whether the first 0, 4 or 8 byte of KeySource
// are valid depends on the KeyIdMode parameter
uint8_t SecurityLevel;
uint8_t KeyIdMode;
uint8_t KeySource[8];
uint8_t KeyIndex;
} ieee154_security_t;
typedef nx_struct
{
nxle_uint8_t AlternatePANCoordinator :1;
nxle_uint8_t DeviceType :1;
nxle_uint8_t PowerSource :1;
nxle_uint8_t ReceiverOnWhenIdle :1;
nxle_uint8_t Reserved :2;
nxle_uint8_t SecurityCapability :1;
nxle_uint8_t AllocateAddress :1;
} ieee154_CapabilityInformation_t;
typedef nx_struct
{
nxle_uint8_t BeaconOrder :4;
nxle_uint8_t SuperframeOrder :4;
nxle_uint8_t FinalCAPSlot :4;
nxle_uint8_t BatteryLifeExtension :1;
nxle_uint8_t Reserved :1;
nxle_uint8_t PANCoordinator :1;
nxle_uint8_t AssociationPermit :1;
} ieee154_SuperframeSpec_t;
typedef struct ieee154_PANDescriptor {
uint8_t CoordAddrMode;
uint16_t CoordPANId;
ieee154_address_t CoordAddress;
uint8_t LogicalChannel;
uint8_t ChannelPage;
ieee154_SuperframeSpec_t SuperframeSpec;
bool GTSPermit;
uint8_t LinkQuality;
uint32_t TimeStamp;
ieee154_status_t SecurityFailure;
uint8_t SecurityLevel;
uint8_t KeyIdMode;
uint64_t KeySource;
uint8_t KeyIndex;
} ieee154_PANDescriptor_t;
enum {
// Values for the PANType parameter of the MLME_RESET.request primitive
BEACON_ENABLED_PAN,
NONBEACON_ENABLED_PAN,
// Values for the TxOptions parameter of MCPS_DATA.request()
TX_OPTIONS_ACK = 0x01,
TX_OPTIONS_GTS = 0x02,
TX_OPTIONS_INDIRECT = 0x04,
// Values for Destination/Source Addressing Mode (MCPS_DATA.request(), etc.)
ADDR_MODE_NOT_PRESENT = 0x00,
ADDR_MODE_RESERVED = 0x01,
ADDR_MODE_SHORT_ADDRESS = 0x02,
ADDR_MODE_EXTENDED_ADDRESS = 0x03,
// ScanType parameter for MLME-SCAN primitive
ENERGY_DETECTION_SCAN = 0x00,
ACTIVE_SCAN = 0x01,
PASSIVE_SCAN = 0x02,
ORPHAN_SCAN = 0x03,
// Frame types
FRAMETYPE_BEACON = 0x00,
FRAMETYPE_DATA = 0x01,
FRAMETYPE_ACK = 0x02,
FRAMETYPE_CMD = 0x03,
};
/****************************************************
* typedefs PIB value types
*/
typedef uint8_t ieee154_phyCurrentChannel_t;
typedef uint32_t ieee154_phyChannelsSupported_t;
typedef uint8_t ieee154_phyTransmitPower_t;
typedef uint8_t ieee154_phyCCAMode_t;
typedef uint8_t ieee154_phyCurrentPage_t;
typedef uint16_t ieee154_phyMaxFrameDuration_t;
typedef uint8_t ieee154_phySHRDuration_t;
typedef uint8_t ieee154_phySymbolsPerOctet_t;
typedef uint8_t ieee154_macAckWaitDuration_t;
typedef bool ieee154_macAssociatedPANCoord_t;
typedef bool ieee154_macAssociationPermit_t;
typedef bool ieee154_macAutoRequest_t;
typedef bool ieee154_macBattLifeExt_t;
typedef uint8_t ieee154_macBattLifeExtPeriods_t;
typedef uint8_t* ieee154_macBeaconPayload_t;
typedef uint8_t ieee154_macBeaconPayloadLength_t;
typedef uint8_t ieee154_macBeaconOrder_t;
typedef uint32_t ieee154_macBeaconTxTime_t;
typedef uint8_t ieee154_macBSN_t;
typedef uint64_t ieee154_macCoordExtendedAddress_t;
typedef uint16_t ieee154_macCoordShortAddress_t;
typedef uint8_t ieee154_macDSN_t;
typedef bool ieee154_macGTSPermit_t;
typedef uint8_t ieee154_macMaxBE_t;
typedef uint8_t ieee154_macMaxCSMABackoffs_t;
typedef uint32_t ieee154_macMaxFrameTotalWaitTime_t;
typedef uint8_t ieee154_macMaxFrameRetries_t;
typedef uint8_t ieee154_macMinBE_t;
typedef uint8_t ieee154_macMinLIFSPeriod_t;
typedef uint8_t ieee154_macMinSIFSPeriod_t;
typedef uint16_t ieee154_macPANId_t;
typedef bool ieee154_macPromiscuousMode_t;
typedef uint8_t ieee154_macResponseWaitTime_t;
typedef bool ieee154_macRxOnWhenIdle_t;
typedef bool ieee154_macSecurityEnabled_t;
typedef uint16_t ieee154_macShortAddress_t;
typedef uint8_t ieee154_macSuperframeOrder_t;
typedef uint16_t ieee154_macSyncSymbolOffset_t;
typedef bool ieee154_macTimestampSupported_t;
typedef uint16_t ieee154_macTransactionPersistenceTime_t;
// own typedefs
typedef bool ieee154_macPanCoordinator_t;
// When security is implemented the following line should be commented out
#define IEEE154_SECURITY_DISABLED
/****************************************************
* Static memory allocation for Queue/Pool
*/
#ifndef TXFRAME_POOL_SIZE
#define TXFRAME_POOL_SIZE 5
#endif
#ifndef TXCONTROL_POOL_SIZE
#define TXCONTROL_POOL_SIZE 5
#endif
#ifndef CAP_TX_QUEUE_SIZE
#define CAP_TX_QUEUE_SIZE 10
#endif
#ifndef INDIRECT_TX_QUEUE_SIZE
#define INDIRECT_TX_QUEUE_SIZE 7
#endif
#ifndef MAX_PENDING_ASSOC_RESPONSES
#define MAX_PENDING_ASSOC_RESPONSES INDIRECT_TX_QUEUE_SIZE
#endif
enum {
// PHY sublayer constant needed to calculate mpdu size
IEEE154_aMaxPHYPacketSize = 127,
};
#endif // __TKN154_H
--- NEW FILE: TKN154_MAC.h ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#ifndef __TKN154_MAC_H
#define __TKN154_MAC_H
#include "TKN154.h"
#include "TKN154_PHY.h"
/****************************************************
* IEEE 802.15.4 PAN information base identifiers
**/
enum {
// PHY Sublayer PIB
IEEE154_phyCurrentChannel = 0x00,
IEEE154_phyChannelsSupported = 0x01,
IEEE154_phyTransmitPower = 0x02,
IEEE154_phyCCAMode = 0x03,
IEEE154_phyCurrentPage = 0x04,
IEEE154_phyMaxFrameDuration = 0x05,
IEEE154_phySHRDuration = 0x06,
IEEE154_phySymbolsPerOctet = 0x07,
// MAC Sublayer PIB
IEEE154_macAckWaitDuration = 0x40,
IEEE154_macAssociatedPANCoord = 0x56,
IEEE154_macAssociationPermit = 0x41,
IEEE154_macAutoRequest = 0x42,
IEEE154_macBattLifeExt = 0x43,
IEEE154_macBattLifeExtPeriods = 0x44,
IEEE154_macBeaconPayload = 0x45,
IEEE154_macBeaconPayloadLength = 0x46,
IEEE154_macBeaconOrder = 0x47,
IEEE154_macBeaconTxTime = 0x48,
IEEE154_macBSN = 0x49,
IEEE154_macCoordExtendedAddress = 0x4A,
IEEE154_macCoordShortAddress = 0x4B,
IEEE154_macDSN = 0x4C,
IEEE154_macGTSPermit = 0x4D,
IEEE154_macMaxBE = 0x57,
IEEE154_macMaxCSMABackoffs = 0x4E,
IEEE154_macMaxFrameTotalWaitTime = 0x58,
IEEE154_macMaxFrameRetries = 0x59,
IEEE154_macMinBE = 0x4F,
// no identifier defined in standard
IEEE154_macMinLIFSPeriod = 0xA0,
// no identifier defined in standard
IEEE154_macMinSIFSPeriod = 0xA1,
IEEE154_macPANId = 0x50,
IEEE154_macPromiscuousMode = 0x51,
IEEE154_macResponseWaitTime = 0x5A,
IEEE154_macRxOnWhenIdle = 0x52,
IEEE154_macSecurityEnabled = 0x5D,
IEEE154_macShortAddress = 0x53,
IEEE154_macSuperframeOrder = 0x54,
IEEE154_macSyncSymbolOffset = 0x5B,
IEEE154_macTimestampSupported = 0x5C,
IEEE154_macTransactionPersistenceTime = 0x55,
// attributes not present in the standard PIB:
IEEE154_macPanCoordinator = 0xF0,
};
enum {
// MAC header indices
MHR_INDEX_FC1 = 0,
MHR_INDEX_FC2 = 1,
MHR_INDEX_SEQNO = 2,
MHR_INDEX_ADDRESS = 3,
MHR_MAX_LEN = 23,
// Frame Control field in MHR
FC1_FRAMETYPE_BEACON = 0x00,
FC1_FRAMETYPE_DATA = 0x01,
FC1_FRAMETYPE_ACK = 0x02,
FC1_FRAMETYPE_CMD = 0x03,
FC1_FRAMETYPE_MASK = 0x07,
FC1_SECURITY_ENABLED = 0x08,
FC1_FRAME_PENDING = 0x10,
FC1_ACK_REQUEST = 0x20,
FC1_PAN_ID_COMPRESSION = 0x40,
FC2_DEST_MODE_SHORT = 0x08,
FC2_DEST_MODE_EXTENDED = 0x0c,
FC2_DEST_MODE_MASK = 0x0c,
FC2_DEST_MODE_OFFSET = 2,
FC2_SRC_MODE_SHORT = 0x80,
FC2_SRC_MODE_EXTENDED = 0xc0,
FC2_SRC_MODE_MASK = 0xc0,
FC2_SRC_MODE_OFFSET = 6,
FC2_FRAME_VERSION_1 = 0x10,
FC2_FRAME_VERSION_2 = 0x20,
FC2_FRAME_VERSION_MASK = 0x30,
};
#define CAP_TX_CLIENT "CapQueueP.FrameTx.client"
#define INDIRECT_TX_CLIENT "IndirectTx.client"
#define IEEE802154_RADIO_RESOURCE "RadioRxTxP.resource"
enum {
OUTGOING_SUPERFRAME,
INCOMING_SUPERFRAME,
};
typedef struct {
uint8_t length; // top bit denotes -> promiscuous mode
uint8_t mhr[MHR_MAX_LEN];
} ieee154_header_t;
typedef struct {
uint8_t rssi;
uint8_t linkQuality;
uint32_t timestamp;
} ieee154_metadata_t;
typedef struct
{
uint8_t client;
uint8_t handle;
ieee154_header_t *header;
uint8_t headerLen;
uint8_t *payload;
uint8_t payloadLen;
ieee154_metadata_t *metadata;
} ieee154_txframe_t;
typedef struct
{
ieee154_header_t header;
ieee154_metadata_t metadata;
} ieee154_txcontrol_t;
typedef struct {
ieee154_txframe_t *frame;
ieee154_macMaxBE_t BE;
ieee154_macMaxCSMABackoffs_t allowedBackoffs;
ieee154_macMaxBE_t macMaxBE;
uint16_t backoff;
uint16_t backoffElapsed;
uint32_t transactionTime;
} ieee154_cap_frame_backup_t;
#define MHR(x) (((ieee154_header_t*) (x)->header)->mhr)
// COMMAND frames
enum {
CMD_FRAME_ASSOCIATION_REQUEST = 1,
CMD_FRAME_ASSOCIATION_RESPONSE = 2,
CMD_FRAME_DISASSOCIATION_NOTIFICATION = 3,
CMD_FRAME_DATA_REQUEST = 4,
CMD_FRAME_PAN_ID_CONFLICT_NOTIFICATION = 5,
CMD_FRAME_ORPHAN_NOTIFICATION = 6,
CMD_FRAME_BEACON_REQUEST = 7,
CMD_FRAME_COORDINATOR_REALIGNMENT = 8,
CMD_FRAME_GTS_REQUEST = 9
};
enum {
// MAC payload fields inside a beacon frame
BEACON_INDEX_SF_SPEC1 = 0,
BEACON_INDEX_SF_SPEC2 = 1,
BEACON_INDEX_GTS_SPEC = 2,
SF_SPEC2_PAN_COORD = 0x40,
SF_SPEC2_ASSOCIATION_PERMIT = 0x80,
GTS_DESCRIPTOR_COUNT_MASK = 0x07,
GTS_LENGTH_MASK = 0xF0,
GTS_LENGTH_OFFSET = 4,
GTS_SPEC_PERMIT = 0x80,
PENDING_ADDRESS_SHORT_MASK = 0x07,
PENDING_ADDRESS_EXT_MASK = 0x70,
};
enum {
// PHY sublayer constants
IEEE154_aTurnaroundTime = 12,
FRAMECTL_LENGTH_MASK = 0x7F, // "length" member in ieee154_frame_t
FRAMECTL_PROMISCUOUS = 0x80, // "length" member in ieee154_frame_t
};
#define IEEE154_SUPPORTED_CHANNELPAGE (IEEE154_SUPPORTED_CHANNELS >> 27)
enum {
// MAC sublayer constants
IEEE154_aNumSuperframeSlots = 16,
IEEE154_aMaxMPDUUnsecuredOverhead = 25,
IEEE154_aMinMPDUOverhead = 9,
IEEE154_aBaseSlotDuration = 60,
IEEE154_aBaseSuperframeDuration = (IEEE154_aBaseSlotDuration * IEEE154_aNumSuperframeSlots),
IEEE154_aGTSDescPersistenceTime = 4,
IEEE154_aMaxBeaconOverhead = 75,
IEEE154_aMaxBeaconPayloadLength = (IEEE154_aMaxPHYPacketSize - IEEE154_aMaxBeaconOverhead),
IEEE154_aMaxLostBeacons = 4,
IEEE154_aMaxMACSafePayloadSize = (IEEE154_aMaxPHYPacketSize - IEEE154_aMaxMPDUUnsecuredOverhead),
IEEE154_aMaxMACPayloadSize = (IEEE154_aMaxPHYPacketSize - IEEE154_aMinMPDUOverhead),
IEEE154_aMaxSIFSFrameSize = 18,
IEEE154_aMinCAPLength = 440,
IEEE154_aUnitBackoffPeriod = 20,
};
#endif // __TKN154_MAC_H
--- NEW FILE: TKN154_PIB.h ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Date: 2008/06/16 18:00:29 $
* @author Torsten Halbhuebner <hhuebner.tu-berlin.de>
* ========================================================================
*/
#ifndef __TKN154_PIB_H
#define __TKN154_PIB_H
/****************************************************
* IEEE 802.15.4 PAN information base (PIB)
*/
typedef struct ieee154_PIB_t {
/**************/
/* bool types */
/**************/
// 0x41
ieee154_macAssociationPermit_t macAssociationPermit;
// 0x42
ieee154_macAutoRequest_t macAutoRequest;
// 0x43
ieee154_macBattLifeExt_t macBattLifeExt;
// 0x4D
ieee154_macGTSPermit_t macGTSPermit;
// 0x51
ieee154_macPromiscuousMode_t macPromiscuousMode;
// 0x52
ieee154_macRxOnWhenIdle_t macRxOnWhenIdle;
// 0x56
ieee154_macAssociatedPANCoord_t macAssociatedPANCoord;
// 0x5D
ieee154_macSecurityEnabled_t macSecurityEnabled;
// no standard attribute
ieee154_macPanCoordinator_t macPanCoordinator;
/*****************/
/* uint8_t types */
/*****************/
// 0x00
ieee154_phyCurrentChannel_t phyCurrentChannel;
// 0x02
ieee154_phyTransmitPower_t phyTransmitPower;
// 0x03
ieee154_phyCCAMode_t phyCCAMode;
// 0x04
ieee154_phyCurrentPage_t phyCurrentPage;
// 0x44
ieee154_macBattLifeExtPeriods_t macBattLifeExtPeriods;
// 0x46
ieee154_macBeaconPayloadLength_t macBeaconPayloadLength;
// 0x47
ieee154_macBeaconOrder_t macBeaconOrder;
// 0x49
ieee154_macBSN_t macBSN;
// 0x4C
ieee154_macDSN_t macDSN;
// 0x4E
ieee154_macMaxCSMABackoffs_t macMaxCSMABackoffs;
// 0x4F
ieee154_macMinBE_t macMinBE;
// 0x54
ieee154_macSuperframeOrder_t macSuperframeOrder;
// 0x57
ieee154_macMaxBE_t macMaxBE;
// 0x59
ieee154_macMaxFrameRetries_t macMaxFrameRetries;
// 0x5a
ieee154_macResponseWaitTime_t macResponseWaitTime;
/*****************************/
/* larger than uint8_t types */
/*****************************/
// 0x4B
ieee154_macCoordShortAddress_t macCoordShortAddress;
// 0x50
ieee154_macPANId_t macPANId;
// 0x53
ieee154_macShortAddress_t macShortAddress;
// 0x55
ieee154_macTransactionPersistenceTime_t macTransactionPersistenceTime;
// TODO: check type
ieee154_macMaxFrameTotalWaitTime_t macMaxFrameTotalWaitTime;
ieee154_macBeaconTxTime_t macBeaconTxTime;
// 0x4A
ieee154_macCoordExtendedAddress_t macCoordExtendedAddress;
} ieee154_PIB_t;
// PHY PIB default attributes
#define IEEE154_DEFAULT_CURRENTCHANNEL 26
#define IEEE154_DEFAULT_CHANNELSSUPPORTED_PAGE0 0x07FFF800
#define IEEE154_DEFAULT_CHANNELSSUPPORTED_PAGE1 0
#define IEEE154_DEFAULT_CHANNELSSUPPORTED_PAGE2 0
#define IEEE154_DEFAULT_CCAMODE 3
#define IEEE154_DEFAULT_CURRENTPAGE 0
#define IEEE154_DEFAULT_TRANSMITPOWER_dBm 0
// MAC PIB default attributes
#define IEEE154_DEFAULT_ASSOCIATEDPANCOORD FALSE
#define IEEE154_DEFAULT_ASSOCIATIONPERMIT FALSE
#define IEEE154_DEFAULT_AUTOREQUEST TRUE
#define IEEE154_DEFAULT_BATTLIFEEXT FALSE
#define IEEE154_DEFAULT_BATTLIFEEXTPERIODS 6
#define IEEE154_DEFAULT_BEACONPAYLOAD NULL
#define IEEE154_DEFAULT_BEACONPAYLOADLENGTH 0
#define IEEE154_DEFAULT_BEACONORDER 15
#define IEEE154_DEFAULT_BEACONTXTIME 0
#define IEEE154_DEFAULT_COORDSHORTADDRESS 0xFFFF
#define IEEE154_DEFAULT_GTSPERMIT TRUE
#define IEEE154_DEFAULT_MAXBE 5
#define IEEE154_DEFAULT_MAXCSMABACKOFFS 4
#define IEEE154_DEFAULT_MAXFRAMETOTALWAITTIME 2626
#define IEEE154_DEFAULT_MAXFRAMERETRIES 3
#define IEEE154_DEFAULT_MINBE 3
#define IEEE154_DEFAULT_MINLIFSPERIOD 40
#define IEEE154_DEFAULT_MINSIFSPERIOD 12
#define IEEE154_DEFAULT_PANID 0xFFFF
#define IEEE154_DEFAULT_PROMISCUOUSMODE FALSE
#define IEEE154_DEFAULT_RESPONSEWAITTIME 32
#define IEEE154_DEFAULT_RXONWHENIDLE FALSE
#define IEEE154_DEFAULT_SECURITYENABLED FALSE
#define IEEE154_DEFAULT_SHORTADDRESS 0xFFFF
#define IEEE154_DEFAULT_SUPERFRAMEORDER 15
#define IEEE154_DEFAULT_SYNCSYMBOLOFFSET 0
#define IEEE154_DEFAULT_TIMESTAMPSUPPORTED TRUE
#define IEEE154_DEFAULT_TRANSACTIONPERSISTENCETIME 0x01F4
#define IEEE154_INVALID_TIMESTAMP (0xffffffff)
#endif // __TKN154_PIB_H
--- NEW FILE: TKN154P.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_PHY.h"
#include "TKN154_MAC.h"
#include "TKN154_PIB.h"
#include "TKN154_DEBUG.h"
configuration TKN154P
{
provides
{
// MCPS-SAP
interface MCPS_DATA;
interface MCPS_PURGE;
interface Packet;
// MLME-SAP
interface MLME_ASSOCIATE;
interface MLME_BEACON_NOTIFY;
interface MLME_COMM_STATUS;
interface MLME_DISASSOCIATE;
interface MLME_GET;
/* interface MLME_GTS;*/
interface MLME_ORPHAN;
interface MLME_POLL;
interface MLME_RESET;
interface MLME_RX_ENABLE;
interface MLME_SCAN;
interface MLME_SET;
interface MLME_START;
interface MLME_SYNC;
interface MLME_SYNC_LOSS;
interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
interface IEEE154Frame;
interface IEEE154BeaconFrame;
interface IEEE154TxBeaconPayload;
interface SplitControl as PromiscuousMode;
interface Get<uint64_t> as GetLocalExtendedAddress;
interface TimeCalc;
interface FrameUtility;
} uses {
interface RadioRx;
interface RadioTx;
interface RadioOff;
interface EnergyDetection;
interface SplitControl as PhySplitControl;
interface Set<bool> as RadioPromiscuousMode;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm1;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm2;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm3;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm4;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm5;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm6;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm7;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm8;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm9;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm10;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm11;
interface Alarm<TSymbolIEEE802154,uint32_t> as Alarm12;
interface Timer<TSymbolIEEE802154> as Timer1;
interface Timer<TSymbolIEEE802154> as Timer2;
interface Timer<TSymbolIEEE802154> as Timer3;
interface Timer<TSymbolIEEE802154> as Timer4;
interface Timer<TSymbolIEEE802154> as Timer5;
interface Ieee802154Debug[uint8_t client];
interface LocalTime<TSymbolIEEE802154>;
interface Random;
interface Leds;
}
}
implementation
{
components
#ifndef IEEE154_SCAN_DISABLED
ScanP,
#else
NoScanP as ScanP,
#endif
DataP,
AssociateP,
PollP,
RxEnableP,
IndirectTxP,
PibP,
FrameDispatchP,
#ifndef IEEE154_BEACON_SYNC_DISABLED
BeaconSynchronizeP,
new CapQueueP() as DeviceCapQueue,
new CapP(INCOMING_SUPERFRAME) as DeviceCap,
#else
NoBeaconSynchronizeP as BeaconSynchronizeP,
new NoCapQueueP() as DeviceCapQueue,
new NoCapP() as DeviceCap,
#endif
NoDeviceCfpP as DeviceCfp,
#ifndef IEEE154_BEACON_TX_DISABLED
BeaconTransmitP,
new CapQueueP() as CoordCapQueue,
new CapP(OUTGOING_SUPERFRAME) as CoordCap,
#else
NoBeaconTransmitP as BeaconTransmitP,
new NoCapQueueP() as CoordCapQueue,
new NoCapP() as CoordCap,
#endif
NoCoordCfpP as CoordCfp,
CoordRealignmentP,
CoordBroadcastP,
new PoolC(ieee154_txframe_t, TXFRAME_POOL_SIZE) as TxFramePoolP,
new PoolC(ieee154_txcontrol_t, TXCONTROL_POOL_SIZE) as TxControlPoolP,
new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as DeviceCapQueueC,
new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as CoordCapQueueC,
new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as BroadcastQueueC;
components MainC;
// MCPS
MCPS_DATA = DataP;
MCPS_PURGE = DataP;
//MLME
MLME_START = BeaconTransmitP;
MLME_ASSOCIATE = AssociateP;
MLME_BEACON_NOTIFY = BeaconSynchronizeP;
MLME_BEACON_NOTIFY = ScanP;
MLME_COMM_STATUS = AssociateP;
MLME_COMM_STATUS = CoordRealignmentP;
MLME_DISASSOCIATE = AssociateP;
MLME_GET = PibP;
MLME_ORPHAN = CoordRealignmentP;
/* MLME_GTS = CfpTransmitP;*/
MLME_POLL = PollP;
MLME_RESET = PibP;
MLME_RX_ENABLE = RxEnableP;
MLME_SCAN = ScanP;
MLME_SET = PibP;
MLME_SYNC = BeaconSynchronizeP;
MLME_SYNC_LOSS = BeaconSynchronizeP;
IEEE154Frame = PibP;
IEEE154BeaconFrame = PibP;
PromiscuousMode = RxEnableP;
GetLocalExtendedAddress = PibP.GetLocalExtendedAddress;
IEEE154TxBeaconPayload = BeaconTransmitP;
Packet = PibP;
TimeCalc = PibP;
FrameUtility = PibP;
/* ----------------------- Scanning (MLME-SCAN) ----------------------- */
components new RadioClientC() as ScanRadioClient;
PibP.MacReset -> ScanP;
ScanP.MLME_GET -> PibP;
ScanP.MLME_SET -> PibP.MLME_SET;
ScanP.EnergyDetection = EnergyDetection;
ScanP.RadioRx -> ScanRadioClient;
ScanP.RadioTx -> ScanRadioClient;
ScanP.Frame -> PibP;
ScanP.BeaconFrame -> PibP;
ScanP.RadioOff -> ScanRadioClient;
ScanP.ScanTimer = Timer1;
ScanP.TxFramePool -> TxFramePoolP;
ScanP.TxControlPool -> TxControlPoolP;
ScanP.Token -> ScanRadioClient;
ScanP.FrameUtility -> PibP;
ScanP.Leds = Leds;
/* ----------------- Beacon Transmission (MLME-START) ----------------- */
components new RadioClientC() as StartRadioClient;
PibP.MacReset -> BeaconTransmitP;
BeaconTransmitP.PIBUpdate[IEEE154_macAssociationPermit] -> PibP.PIBUpdate[IEEE154_macAssociationPermit];
BeaconTransmitP.PIBUpdate[IEEE154_macGTSPermit] -> PibP.PIBUpdate[IEEE154_macGTSPermit];
BeaconTransmitP.BeaconTxAlarm = Alarm1;
BeaconTransmitP.BeaconPayloadUpdateTimer = Timer2;
BeaconTransmitP.RadioOff -> StartRadioClient;
BeaconTransmitP.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN;
BeaconTransmitP.BeaconTx -> StartRadioClient;
BeaconTransmitP.MLME_SET -> PibP.MLME_SET;
BeaconTransmitP.MLME_GET -> PibP;
BeaconTransmitP.SetMacSuperframeOrder -> PibP.SetMacSuperframeOrder;
BeaconTransmitP.SetMacBeaconTxTime -> PibP.SetMacBeaconTxTime;
BeaconTransmitP.SetMacPanCoordinator -> PibP.SetMacPanCoordinator;
BeaconTransmitP.Token -> StartRadioClient;
BeaconTransmitP.TokenToBroadcast -> StartRadioClient;
BeaconTransmitP.RealignmentBeaconEnabledTx -> CoordBroadcastP.RealignmentTx;
BeaconTransmitP.RealignmentNonBeaconEnabledTx -> CoordCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
BeaconTransmitP.BeaconRequestRx -> CoordCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_BEACON_REQUEST];
BeaconTransmitP.GtsInfoWrite -> CoordCfp.GtsInfoWrite;
BeaconTransmitP.PendingAddrSpecUpdated -> IndirectTxP.PendingAddrSpecUpdated;
BeaconTransmitP.PendingAddrWrite -> IndirectTxP.PendingAddrWrite;
BeaconTransmitP.FrameUtility -> PibP.FrameUtility;
BeaconTransmitP.IsTrackingBeacons -> BeaconSynchronizeP.IsTrackingBeacons;
BeaconTransmitP.LastBeaconRxRefTime -> BeaconSynchronizeP.CapStartRefTime;
BeaconTransmitP.LastBeaconRxTime -> BeaconSynchronizeP.CapStart;
BeaconTransmitP.GetSetRealignmentFrame -> CoordRealignmentP;
BeaconTransmitP.IsBroadcastReady -> CoordBroadcastP.IsBroadcastReady;
BeaconTransmitP.TimeCalc -> PibP;
BeaconTransmitP.Leds = Leds;
BeaconTransmitP.Debug = Ieee802154Debug[START_CLIENT];
StartRadioClient.TransferTo -> CoordBroadcastRadioClient.TransferFrom;
/* ---------------- Beacon Synchronization (MLME-SYNC) ---------------- */
components new RadioClientC() as SyncRadioClient;
PibP.MacReset -> BeaconSynchronizeP;
BeaconSynchronizeP.MLME_SET -> PibP.MLME_SET;
BeaconSynchronizeP.MLME_GET -> PibP;
BeaconSynchronizeP.TrackAlarm = Alarm2;
BeaconSynchronizeP.FrameUtility -> PibP;
BeaconSynchronizeP.Frame -> PibP;
BeaconSynchronizeP.BeaconFrame -> PibP;
BeaconSynchronizeP.BeaconRx -> SyncRadioClient;
BeaconSynchronizeP.RadioOff -> SyncRadioClient;
BeaconSynchronizeP.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN;
BeaconSynchronizeP.DataRequest -> PollP.DataRequest[SYNC_CLIENT];
BeaconSynchronizeP.Token -> SyncRadioClient;
BeaconSynchronizeP.TokenToCap -> SyncRadioClient;
BeaconSynchronizeP.TimeCalc -> PibP;
BeaconSynchronizeP.CoordRealignmentRx -> DeviceCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_COORDINATOR_REALIGNMENT];
BeaconSynchronizeP.Leds = Leds;
BeaconSynchronizeP.Debug = Ieee802154Debug[SYNC_CLIENT];
SyncRadioClient.TransferTo -> DeviceCapRadioClient.TransferFrom;
/* --------------- Dis/Association (MLME-DIS/ASSOCIATE) --------------- */
PibP.MacReset -> AssociateP;
AssociateP.AssociationRequestRx -> CoordCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_REQUEST];
AssociateP.AssociationRequestTx -> DeviceCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
AssociateP.AssociationResponseExtracted -> DeviceCap.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE];
AssociateP.AssociationResponseTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
AssociateP.DisassociationIndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
AssociateP.DisassociationDirectTx -> CoordCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
AssociateP.DisassociationToCoord -> DeviceCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
AssociateP.DisassociationDirectRxFromCoord ->
DeviceCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
AssociateP.DisassociationExtractedFromCoord ->
DeviceCap.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
AssociateP.DisassociationRxFromDevice ->
CoordCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_CLIENT];
AssociateP.ResponseTimeout = Timer3;
AssociateP.IsTrackingBeacons -> BeaconSynchronizeP.IsTrackingBeacons;
AssociateP.TxFramePool -> TxFramePoolP;
AssociateP.TxControlPool -> TxControlPoolP;
AssociateP.MLME_GET -> PibP;
AssociateP.MLME_SET -> PibP.MLME_SET;
AssociateP.FrameUtility -> PibP;
AssociateP.Frame -> PibP;
AssociateP.Leds = Leds;
AssociateP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
AssociateP.Debug = Ieee802154Debug[ASSOCIATE_CLIENT];
/* ------------------ Data Transmission (MCPS-DATA) ------------------- */
PibP.MacReset -> DataP;
DataP.IsSendingBeacons -> BeaconTransmitP.IsSendingBeacons;
DataP.CoordCapRx -> CoordCap.FrameRx[FC1_FRAMETYPE_DATA];
DataP.DeviceCapTx -> DeviceCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
DataP.CoordCapTx -> CoordCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
DataP.DeviceCapRx -> PollP.DataRx; // indirect
DataP.DeviceCapRx -> RxEnableP.FrameRx; // promiscuous
DataP.DeviceCapRx -> DeviceCap.FrameRx[FC1_FRAMETYPE_DATA]; // broadcast
DataP.TxFramePool -> TxFramePoolP;
DataP.BroadcastTx -> CoordBroadcastP.BroadcastDataFrame;
DataP.DeviceCfpTx -> DeviceCfp.CfpTx;
DataP.IndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
DataP.FrameUtility -> PibP;
DataP.Frame -> PibP;
DataP.PurgeDirect -> DeviceCapQueue;
DataP.PurgeIndirect -> IndirectTxP;
DataP.PurgeGtsDevice -> DeviceCfp;
DataP.PurgeGtsCoord -> CoordCfp;
DataP.MLME_GET -> PibP;
DataP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
DataP.Packet -> PibP;
DataP.Leds = Leds;
/* ------------------------ Polling (MLME-POLL) ----------------------- */
PibP.MacReset -> PollP;
PollP.PollTx -> DeviceCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
PollP.DataExtracted -> DeviceCap.FrameExtracted[FC1_FRAMETYPE_DATA];
PollP.FrameUtility -> PibP;
PollP.TxFramePool -> TxFramePoolP;
PollP.TxControlPool -> TxControlPoolP;
PollP.Debug = Ieee802154Debug[POLL_CLIENT];
PollP.MLME_GET -> PibP;
PollP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
/* ---------------------- Indirect transmission ----------------------- */
PibP.MacReset -> IndirectTxP;
IndirectTxP.CoordCapTx -> CoordCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
IndirectTxP.DataRequestRx -> CoordCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST];
IndirectTxP.MLME_GET -> PibP;
IndirectTxP.FrameUtility -> PibP;
IndirectTxP.IndirectTxTimeout = Timer4;
IndirectTxP.TimeCalc -> PibP;
IndirectTxP.Leds = Leds;
IndirectTxP.Debug = Ieee802154Debug[INDIRECTTX_DEBUG_CLIENT];
/* ---------------------------- Realignment --------------------------- */
PibP.MacReset -> CoordRealignmentP;
CoordRealignmentP.CoordRealignmentTx -> CoordCapQueue.FrameTx[unique(CAP_TX_CLIENT)];
CoordRealignmentP.OrphanNotificationRx -> CoordCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION];
CoordRealignmentP.FrameUtility -> PibP;
CoordRealignmentP.Frame -> PibP;
CoordRealignmentP.TxFramePool -> TxFramePoolP;
CoordRealignmentP.TxControlPool -> TxControlPoolP;
CoordRealignmentP.MLME_GET -> PibP;
CoordRealignmentP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
/* ---------------------------- Broadcasts ---------------------------- */
components new RadioClientC() as CoordBroadcastRadioClient;
PibP.MacReset -> CoordBroadcastP;
CoordBroadcastP.TokenTransferred -> CoordBroadcastRadioClient;
CoordBroadcastP.TokenToCap -> CoordBroadcastRadioClient;
CoordBroadcastRadioClient.TransferTo -> CoordCapRadioClient.TransferFrom;
CoordBroadcastP.BeaconFramePendingBit -> BeaconTransmitP.BeaconFramePendingBit;
CoordBroadcastP.CapTransmitNow -> CoordCap.BroadcastTx;
CoordBroadcastP.Queue -> BroadcastQueueC;
CoordBroadcastP.Leds = Leds;
/* --------------------- CAP (incoming superframe) -------------------- */
PibP.CapQueueReset -> DeviceCapQueue;
DeviceCapQueue.Queue -> DeviceCapQueueC;
DeviceCapQueue.CapTx -> DeviceCap;
PibP.CapQueueReset -> CoordCapQueue;
CoordCapQueue.Queue -> CoordCapQueueC;
CoordCapQueue.CapTx -> CoordCap;
components new RadioClientC() as DeviceCapRadioClient;
PibP.CapReset -> DeviceCap;
DeviceCap.Random = Random;
DeviceCap.CapEndAlarm = Alarm3;
DeviceCap.BLEAlarm = Alarm4;
DeviceCap.IndirectTxWaitAlarm = Alarm5;
DeviceCap.BroadcastAlarm = Alarm6;
DeviceCap.Token -> DeviceCapRadioClient;
DeviceCap.TokenToCfp -> DeviceCapRadioClient;
DeviceCap.TokenTransferred -> DeviceCapRadioClient;
DeviceCap.TokenRequested -> DeviceCapRadioClient;
DeviceCap.IsTokenRequested -> DeviceCapRadioClient;
DeviceCap.CapStart -> BeaconSynchronizeP.CapStart;
DeviceCap.CapStartRefTime -> BeaconSynchronizeP.CapStartRefTime;
DeviceCap.CapLen -> BeaconSynchronizeP.CapLen;
DeviceCap.IsBLEActive -> BeaconSynchronizeP.IsBLEActive;
DeviceCap.BLELen -> BeaconSynchronizeP.BLELen;
DeviceCap.IsRxBroadcastPending -> BeaconSynchronizeP.IsRxBroadcastPending;
DeviceCap.IsRxEnableActive -> RxEnableP.IsRxEnableActive;
DeviceCap.RxEnableStateChange -> RxEnableP.RxEnableStateChange;
DeviceCap.FrameUtility -> PibP;
DeviceCap.RadioTx -> DeviceCapRadioClient;
DeviceCap.RadioRx -> DeviceCapRadioClient;
DeviceCap.RadioOff -> DeviceCapRadioClient;
DeviceCap.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN;
DeviceCap.MLME_GET -> PibP;
DeviceCap.MLME_SET -> PibP.MLME_SET;
DeviceCap.Debug = Ieee802154Debug[DEVICE_CAP_CLIENT];
DeviceCap.TimeCalc -> PibP;
DeviceCap.Leds = Leds;
DeviceCapRadioClient.TransferTo -> DeviceCfpRadioClient.TransferFrom;
/* ---------------------- CAP (outgoing superframe) ------------------- */
components new RadioClientC() as CoordCapRadioClient,
new BackupP(ieee154_cap_frame_backup_t);
PibP.CapReset -> CoordCap;
CoordCap.Random = Random;
CoordCap.CapEndAlarm = Alarm7;
CoordCap.BLEAlarm = Alarm8;
CoordCap.Token -> CoordCapRadioClient;
CoordCap.TokenToCfp -> CoordCapRadioClient;
CoordCap.TokenTransferred -> CoordCapRadioClient;
CoordCap.TokenRequested -> CoordCapRadioClient;
CoordCap.IsTokenRequested -> CoordCapRadioClient;
CoordCap.CapStart -> BeaconTransmitP.CapStart;
CoordCap.CapStartRefTime -> BeaconTransmitP.CapStartRefTime;
CoordCap.CapLen -> BeaconTransmitP.CapLen;
CoordCap.IsBLEActive -> BeaconTransmitP.IsBLEActive;
CoordCap.BLELen -> BeaconTransmitP.BLELen;
CoordCap.IsRxEnableActive -> RxEnableP.IsRxEnableActive;
CoordCap.RxEnableStateChange -> RxEnableP.RxEnableStateChange;
CoordCap.FrameUtility -> PibP;
CoordCap.RadioTx -> CoordCapRadioClient;
CoordCap.RadioRx -> CoordCapRadioClient;
CoordCap.RadioOff -> CoordCapRadioClient;
CoordCap.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN;
CoordCap.MLME_GET -> PibP;
CoordCap.MLME_SET -> PibP.MLME_SET;
CoordCap.Debug = Ieee802154Debug[COORD_CAP_CLIENT];
CoordCap.TimeCalc -> PibP;
CoordCap.Leds = Leds;
CoordCapRadioClient.TransferTo -> CoordCfpRadioClient.TransferFrom;
CoordCap.FrameBackup -> BackupP;
CoordCap.FrameRestore -> BackupP;
/* -------------------- GTS (incoming superframe) --------------------- */
components new RadioClientC() as DeviceCfpRadioClient;
PibP.MacReset -> DeviceCfp;
DeviceCfp.Token -> DeviceCfpRadioClient;
DeviceCfp.TokenTransferred -> DeviceCfpRadioClient;
DeviceCfp.TokenRequested -> DeviceCfpRadioClient;
DeviceCfp.CapStartRefTime -> BeaconSynchronizeP.CapStartRefTime;
DeviceCfp.CfpEnd -> BeaconSynchronizeP.CfpEnd;
DeviceCfp.GtsField -> BeaconSynchronizeP.GtsField;
DeviceCfp.SfSlotDuration -> BeaconSynchronizeP.SfSlotDuration;
DeviceCfp.FinalCapSlot -> BeaconSynchronizeP.FinalCapSlot;
DeviceCfp.CfpSlotAlarm = Alarm9;
DeviceCfp.CfpEndAlarm = Alarm10;
DeviceCfp.RadioTx -> DeviceCfpRadioClient;
DeviceCfp.RadioRx -> DeviceCfpRadioClient;
DeviceCfp.RadioOff -> DeviceCfpRadioClient;
DeviceCfp.MLME_GET -> PibP;
DeviceCfp.MLME_SET -> PibP.MLME_SET;
/* -------------------- GTS (outgoing superframe) --------------------- */
components new RadioClientC() as CoordCfpRadioClient;
PibP.MacReset -> CoordCfp;
CoordCfp.Token -> CoordCfpRadioClient;
CoordCfp.TokenTransferred -> CoordCfpRadioClient;
CoordCfp.TokenRequested -> CoordCfpRadioClient;
CoordCfp.CfpEnd -> BeaconTransmitP.CfpEnd;
CoordCfp.GtsField -> BeaconTransmitP.GtsField;
CoordCfp.SfSlotDuration -> BeaconTransmitP.SfSlotDuration;
CoordCfp.FinalCapSlot -> BeaconTransmitP.FinalCapSlot;
CoordCfp.CfpSlotAlarm = Alarm11;
CoordCfp.CfpEndAlarm = Alarm12;
CoordCfp.RadioTx -> CoordCfpRadioClient;
CoordCfp.RadioRx -> CoordCfpRadioClient;
CoordCfp.RadioOff -> CoordCfpRadioClient;
CoordCfp.MLME_GET -> PibP;
CoordCfp.MLME_SET -> PibP.MLME_SET;
/* ------------------ MLME-RX-ENABLE / promiscuous mode --------------- */
components new RadioClientC() as RxEnableRadioClient;
PibP.MacReset -> RxEnableP;
RxEnableP.Token -> RxEnableRadioClient;
RxEnableP.PromiscuousRx -> RxEnableRadioClient;
RxEnableP.IncomingSfStart -> BeaconSynchronizeP.CapStart;
RxEnableP.OutgoingSfStart -> BeaconTransmitP.CapStart;
RxEnableP.IncomingBeaconInterval -> BeaconSynchronizeP.BeaconInterval;
RxEnableP.OutgoingBeaconInterval -> BeaconTransmitP.BeaconInterval;
RxEnableP.IsTrackingBeacons -> BeaconSynchronizeP.IsTrackingBeacons;
RxEnableP.IsSendingBeacons-> BeaconTransmitP.IsSendingBeacons;
RxEnableP.IsMacPanCoordinator -> PibP.IsMacPanCoordinator;
RxEnableP.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN;
RxEnableP.TimeCalc -> PibP.TimeCalc;
RxEnableP.RadioOff -> RxEnableRadioClient;
RxEnableP.RadioPromiscuousMode = RadioPromiscuousMode;
RxEnableP.WasRxEnabled -> DeviceCap;
RxEnableP.WasRxEnabled -> CoordCap;
RxEnableP.RxEnableTimer = Timer5;
RxEnableP.Debug = Ieee802154Debug[RXENABLE_CLIENT];
/* ------------------------------- PIB -------------------------------- */
components new RadioClientC() as PibRadioClient;
PIBUpdate = PibP;
MainC.SoftwareInit -> PibP.LocalInit;
PibP.RadioControl = PhySplitControl;
PibP.Random = Random;
PibP.PromiscuousModeGet -> RxEnableP;
PibP.LocalTime = LocalTime;
PibP.Token -> PibRadioClient;
PibP.RadioOff -> PibRadioClient;
/* ---------------------------- Dispatcher ---------------------------- */
FrameDispatchP.PhyTx = RadioTx;
FrameDispatchP.PhyRx = RadioRx;
FrameDispatchP.PhyRadioOff = RadioOff;
FrameDispatchP.RadioPromiscuousMode -> RxEnableP;
FrameDispatchP.Leds = Leds;
FrameDispatchP.Debug = Ieee802154Debug[RADIORXTX_CLIENT];
}
--- NEW FILE: TransferClientP.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:00:29 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
generic module TransferClientP(uint8_t myUserId)
{
provides
{
interface ResourceTransfer;
interface ResourceTransferred;
interface ResourceTransferConnector as TransferredFrom;
} uses {
interface ResourceTransferConnector as TransferTo;
interface ResourceTransferControl;
interface Leds;
}
}
implementation
{
async command error_t ResourceTransfer.transfer()
{
error_t result;
uint8_t toClient = call TransferTo.getUserId();
atomic {
result = call ResourceTransferControl.transfer(myUserId, toClient);
if (result == SUCCESS)
call TransferTo.transfer();
}
return result;
}
async command uint8_t TransferredFrom.getUserId(){ return myUserId;}
async command void TransferredFrom.transfer()
{
signal ResourceTransferred.transferred();
}
async command error_t ResourceTransferred.release()
{
return call ResourceTransferControl.release(myUserId);
}
default async command uint8_t TransferTo.getUserId(){ call Leds.led0On(); return 0xFF;}
default async command void TransferTo.transfer(){ call Leds.led0On(); }
}
More information about the Tinyos-2-commits
mailing list