📄 framerm.nc
字号:
// $Id: FramerM.nc,v 1.2.2.1 2004/07/14 19:00:38 kristinwright Exp $
/* -*- Mode: C; c-basic-indent: 2; indent-tabs-mode: nil -*- */
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
* downloading, copying, installing or using the software you agree to
* this license. If you do not agree to this license, do not download,
* install, copy or use the software.
*
* Intel Open Source License
*
* Copyright (c) 2002 Intel Corporation
* 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 Intel Corporation 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 INTEL OR ITS
* 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.
*
* Author: Phil Buonadonna
* Revision: $Revision: 1.2.2.1 $
*
*/
/*
* FramerM
*
* This modules provides framing for TOS_Msg's using PPP-HDLC-like framing
* (see RFC 1662). When sending, a TOS_Msg is encapsulated in an HLDC frame.
* Receiving is similar EXCEPT that the component expects a special token byte
* be received before the data payload. The purpose of the token is to feed back
* an acknowledgement to the sender which serves as a crude form of flow-control.
* This module is intended for use with the Packetizer class found in
* tools/java/net/packet/Packetizer.java.
*
*/
/**
* @author Phil Buonadonna
*/
includes AM;
includes crc;
module FramerM {
provides {
interface StdControl;
interface TokenReceiveMsg;
interface ReceiveMsg;
interface BareSendMsg;
}
uses {
interface ByteComm;
interface StdControl as ByteControl;
}
}
implementation {
enum {
HDLC_QUEUESIZE = 2,
HDLC_MTU = (sizeof(TOS_Msg)),
HDLC_FLAG_BYTE = 0x7e,
HDLC_CTLESC_BYTE = 0x7d,
PROTO_ACK = 64,
PROTO_PACKET_ACK = 65,
PROTO_PACKET_NOACK = 66,
PROTO_UNKNOWN = 255
};
enum {
RXSTATE_NOSYNC,
RXSTATE_PROTO,
RXSTATE_TOKEN,
RXSTATE_INFO,
RXSTATE_ESC
};
enum {
TXSTATE_IDLE,
TXSTATE_PROTO,
TXSTATE_INFO,
TXSTATE_ESC,
TXSTATE_FCS1,
TXSTATE_FCS2,
TXSTATE_ENDFLAG,
TXSTATE_FINISH,
TXSTATE_ERROR
};
enum {
FLAGS_TOKENPEND = 0x2,
FLAGS_DATAPEND = 0x4,
FLAGS_UNKNOWN = 0x8
};
TOS_Msg gMsgRcvBuf[HDLC_QUEUESIZE];
typedef struct _MsgRcvEntry {
uint8_t Proto;
uint8_t Token; // Used for sending acknowledgements
uint16_t Length; // Does not include 'Proto' or 'Token' fields
TOS_MsgPtr pMsg;
} MsgRcvEntry_t ;
MsgRcvEntry_t gMsgRcvTbl[HDLC_QUEUESIZE];
uint8_t * gpRxBuf;
uint8_t * gpTxBuf;
uint8_t gFlags;
// Flags variable protects atomicity
norace uint8_t gTxState;
norace uint8_t gPrevTxState;
norace uint8_t gTxProto;
norace uint16_t gTxByteCnt;
norace uint16_t gTxLength;
norace uint16_t gTxRunningCRC;
uint8_t gRxState;
uint8_t gRxHeadIndex;
uint8_t gRxTailIndex;
uint16_t gRxByteCnt;
uint16_t gRxRunningCRC;
MyTOS_MsgPtr MygpTxMsg;
TOS_MsgPtr gpTxMsg;
uint8_t gTxTokenBuf;
uint8_t gTxUnknownBuf;
norace uint8_t gTxEscByte;
task void MyPacketSent();
task void PacketSent();
uint8_t fRemapRxPos( uint8_t InPos ); //remap standard TOSMessage fields to CC2420TOSMsg
//*************************************************************************
/*
fRemapRxPos
Map incomming byte positions into new TOSmessage structure
Does NOT handle CRC bytes correctly
*/
uint8_t fRemapRxPos( uint8_t InPos ) {
if( InPos<4 )
return( InPos+offsetof(struct TOS_Msg, addr) ); //addr,AM,groupid
else if( InPos==4 )
return( offsetof(struct TOS_Msg, length) ); //length
else return( offsetof(struct TOS_Msg, data) ); //data and subsequent
}//fRemapRxByte
result_t StartTx() {
result_t Result = SUCCESS;
bool fInitiate = FALSE;
atomic {
if (gTxState == TXSTATE_IDLE) {
if (gFlags & FLAGS_TOKENPEND) {
gpTxBuf = (uint8_t *)&gTxTokenBuf;
gTxProto = PROTO_ACK;
gTxLength = sizeof(gTxTokenBuf);
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
else if (gFlags & FLAGS_DATAPEND) {
gpTxBuf = (uint8_t *)gpTxMsg;
gTxProto = PROTO_PACKET_NOACK;
// gTxLength = gpTxMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
//number of bytes to xfer = TOSHeader + data + 2CRC bytes
gTxLength = gpTxMsg->length + TOS_HEADER_SIZE + 2+3;
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
else if (gFlags & FLAGS_UNKNOWN) {
gpTxBuf = (uint8_t *)&gTxUnknownBuf;
gTxProto = PROTO_UNKNOWN;
gTxLength = sizeof(gTxUnknownBuf);
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
}
}
if (fInitiate) {
atomic {
gTxRunningCRC = 0; //initialize CRC calculation
// gTxByteCnt = 6; //start at addr in tosmsg
gTxByteCnt = offsetof(struct TOS_Msg, addr); //start at TOSaddr field
}
Result = call ByteComm.txByte(HDLC_FLAG_BYTE);
if (Result != SUCCESS) {
atomic gTxState = TXSTATE_ERROR;
post PacketSent();
}
}
return Result;
}
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
result_t MyStartTx() {
result_t Result = SUCCESS;
bool fInitiate = FALSE;
atomic {
if (gTxState == TXSTATE_IDLE) {
if (gFlags & FLAGS_TOKENPEND) {
gpTxBuf = (uint8_t *)&gTxTokenBuf;
gTxProto = PROTO_ACK;
gTxLength = sizeof(gTxTokenBuf);
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
else if (gFlags & FLAGS_DATAPEND) {
gpTxBuf = (uint8_t *)gpTxMsg;
gTxProto = PROTO_PACKET_NOACK;
// gTxLength = gpTxMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
//number of bytes to xfer = TOSHeader + data + 2CRC bytes
gTxLength = MygpTxMsg->length + TOS_HEADER_SIZE + 2+3;
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
else if (gFlags & FLAGS_UNKNOWN) {
gpTxBuf = (uint8_t *)&gTxUnknownBuf;
gTxProto = PROTO_UNKNOWN;
gTxLength = sizeof(gTxUnknownBuf);
fInitiate = TRUE;
gTxState = TXSTATE_PROTO;
}
}
}
if (fInitiate) {
atomic {
gTxRunningCRC = 0; //initialize CRC calculation
// gTxByteCnt = 6; //start at addr in tosmsg
gTxByteCnt = offsetof(struct MyTOS_Msg, addr); //start at TOSaddr field
}
Result = call ByteComm.txByte(HDLC_FLAG_BYTE);
if (Result != SUCCESS) {
atomic gTxState = TXSTATE_ERROR;
post MyPacketSent();
}
}
return Result;
}
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
task void MyPacketSent() {
result_t TxResult = SUCCESS;
atomic {
if (gTxState == TXSTATE_ERROR) {
TxResult = FAIL;
gTxState = TXSTATE_IDLE;
}
}
if (gTxProto == PROTO_ACK) {
atomic gFlags ^= FLAGS_TOKENPEND;
}
else{
atomic gFlags ^= FLAGS_DATAPEND;
signal BareSendMsg.MysendDone((MyTOS_MsgPtr)MygpTxMsg,TxResult);
atomic MygpTxMsg = NULL;
}
// Trigger transmission in case something else is pending
MyStartTx();
}
task void PacketUnknown() {
atomic {
gFlags |= FLAGS_UNKNOWN;
}
StartTx();
}
task void PacketRcvd() {
MsgRcvEntry_t *pRcv = &gMsgRcvTbl[gRxTailIndex];
TOS_MsgPtr pBuf = pRcv->pMsg;
// Does the rcvd frame actually have a meaningful message??
if (pRcv->Length >= offsetof(struct TOS_Msg,data)) {
switch (pRcv->Proto) {
case PROTO_ACK:
break;
case PROTO_PACKET_ACK:
pBuf->crc = 1; // Easier to set here...
pBuf = signal TokenReceiveMsg.receive(pBuf,pRcv->Token);
break;
case PROTO_PACKET_NOACK:
pBuf->crc = 1;
pBuf = signal ReceiveMsg.receive(pBuf);
break;
default:
gTxUnknownBuf = pRcv->Proto;
post PacketUnknown();
break;
} //switch
} //if
atomic {
if (pBuf) {
pRcv->pMsg = pBuf;
}
pRcv->Length = 0;
pRcv->Token = 0;
gRxTailIndex++;
gRxTailIndex %= HDLC_QUEUESIZE;
}
}
task void PacketSent() {
result_t TxResult = SUCCESS;
atomic {
if (gTxState == TXSTATE_ERROR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -