📄 phyradiom.nc
字号:
// $Id: PhyRadioM.nc,v 1.1 2004/03/04 20:21:14 weiyeisi Exp $/* Copyright (c) 2002 the University of Southern California. * 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 and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF SOUTHERN CALIFORNIA 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 THE * UNIVERSITY OF SOUTHERN CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * THE UNIVERSITY OF SOUTHERN CALIFORNIA 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 THE UNIVERSITY OF SOUTHERN CALIFORNIA HAS NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. * *//* Authors: Wei Ye * Date created: 1/21/2003 * * This is the physical layer that sends and receives a packet * - accept any type and length (<= PHY_MAX_PKT_LEN in phy_radio_msg.h) of packet * - sending a packet: encoding and byte spooling * - receiving a packet: decoding, byte buffering * - Optional CRC check (CRC calculation is based on code from Jason Hill) * - interface to radio control and physical carrier sense * *//** * @author Wei Ye */includes uartDebug;module PhyRadioM{ provides { interface StdControl as PhyControl; interface RadioState as PhyState; interface PhyComm; interface PhyStreamByte; } uses { interface StdControl as RadControl; interface RadioState; interface RadioByte; interface StdControl as CodecControl; interface RadioEncoding as Codec; }}implementation{#include "PhyRadioMsg.h"#include "smacEvents.h" // Physical layer states enum { IDLE, RECEIVING, TRANSMITTING, TRANSMITTING_LAST, TRANSMITTING_DONE }; // buffer states enum {FREE, BUSY}; char state; uint8_t pktLength; // pkt length including my header and trailer PhyPktBuf buffer1; // 2 buffers for receiving and processing PhyPktBuf buffer2; char recvBufState; // receiving buffer state char procBufState; // processing buffer state char* procBufPtr; char* sendPtr; char* recvPtr; char* procPtr; uint8_t recvCount; uint8_t numEncoded; char txBuffer[3]; uint8_t bufHead; uint8_t bufEnd; int16_t crcRx; // CRC of received pkt int16_t crcTx; // CRC of transmitted pkt int16_t update_crc(char data, int16_t crc) { char i; int16_t tmp; tmp = (int16_t)(data); crc = crc ^ (tmp << 8); for (i = 0; i < 8; i++) { if (crc & 0x8000) crc = crc << 1 ^ 0x1021; // << is done before ^ else crc = crc << 1; } return crc; } task void packet_received() { void* tmp; char error, intEnabled; uint8_t len; len = (uint8_t)procPtr[0]; if (crcRx != *(int16_t*)(procPtr + len - 2)) { error = 1; } else { error = 0; } tmp = signal PhyComm.rxPktDone(procPtr, error); if (tmp) { intEnabled = inp(SREG) & 0x80; cli(); if (recvBufState == BUSY) { // waiting for a free buffer procPtr = recvPtr; recvPtr = (char*)tmp; recvBufState = FREE; // can start receive now } else { procPtr = NULL; procBufPtr = (char*)tmp; procBufState = FREE; } if (intEnabled) sei(); if (procPtr) { // have a buffered packet to signal if (!post packet_received()) { // task queue is full procBufPtr = procPtr; //drop packet procBufState = FREE; signal PhyComm.rxPktDone(NULL, 1); // signal in case MAC is waiting } } } } task void packet_sent() { signal PhyComm.txPktDone(sendPtr); } command result_t PhyControl.init() { state = IDLE; recvPtr = (char*)&buffer1; procBufPtr = (char*)&buffer2; recvBufState = FREE; procBufState = FREE; call RadControl.init(); return SUCCESS; } command result_t PhyControl.start() { return SUCCESS; } command result_t PhyControl.stop() { return SUCCESS; } command result_t PhyState.idle() { call RadioState.idle(); state = IDLE; return SUCCESS; } command result_t PhyState.sleep() { call RadioState.sleep(); state = IDLE; return SUCCESS; } command result_t PhyComm.txPkt(void* packet, uint8_t length) { if (length > PHY_MAX_PKT_LEN || length < PHY_MIN_PKT_LEN) return FAIL; if (state != IDLE && state != RECEIVING) return FAIL; state = TRANSMITTING; call RadioByte.startTx(); // tell radio to start sending sendPtr = (char*)packet; ((PhyHeader*)sendPtr)->length = length; // fill my header field pktLength = length; // encode first byte of the packet bufHead = 0; bufEnd = 0; call Codec.encode(sendPtr[0]); numEncoded = 1; crcTx=update_crc(sendPtr[0], 0); return SUCCESS; } // default do-nothing event handler for PhyComm interface default event result_t PhyComm.txPktDone(void* packet) { return SUCCESS; } default event result_t PhyComm.startSymDetected(void* packet) { return SUCCESS; } default event void* PhyComm.rxPktDone(void* packet, char error) { return packet; } async event result_t Codec.encodeDone(char data) { txBuffer[bufEnd] = data; bufEnd++; return SUCCESS; } async event result_t Codec.decodeDone(char data, char error) { // one byte is decoded if (recvCount == 0) { // first byte is packet length if (error == 1 || (uint8_t)data > PHY_MAX_PKT_LEN || (uint8_t)data < PHY_MIN_PKT_LEN) { call RadioState.idle(); state = IDLE; // signal received an erroneous packet with NULL buffer // unknown length (0) and error flag setting to 1 signal PhyComm.rxPktDone(NULL, 1); return FAIL; } pktLength = (uint8_t)data; crcRx = 0; } recvPtr[recvCount] = data; recvCount++; // pass data for upper layer to stream bytes (e.g. snooper) signal PhyStreamByte.rxByteDone(data); if (recvCount < pktLength - 1) { crcRx=update_crc(data, crcRx); } else if (recvCount == pktLength) { // Rx packet done if (procBufState == FREE) { // have a free buffer, use it now procPtr = recvPtr; recvPtr = procBufPtr; recvBufState = FREE; if (post packet_received()) { // signal upper layer procBufState = BUSY; } else { // task queue is full procBufPtr = procPtr; //drop packet signal PhyComm.rxPktDone(NULL, 1); // signal in case MAC is waiting } } else { // no buffer to use for Rx recvBufState = BUSY; } call CodecControl.init(); call RadioState.idle(); state = IDLE; } return SUCCESS; } // default do-nothing handler for PhyStreamByte default event result_t PhyStreamByte.rxByteDone(char data) { return SUCCESS; } event result_t RadioByte.txByteReady() { // radio asks a byte to transmit if(state == TRANSMITTING) { call RadioByte.txNextByte(txBuffer[bufHead]); bufHead++; //now check if that was the last byte if (bufHead == bufEnd) { bufHead = 0; bufEnd = 0; if (numEncoded < pktLength) { if(numEncoded < pktLength - 2){ crcTx=update_crc(sendPtr[numEncoded], crcTx); } call Codec.encode(sendPtr[numEncoded]); numEncoded++; if(numEncoded == pktLength - 2){ *(int16_t*)(sendPtr + pktLength - 2) = crcTx; } } else { call Codec.encode_flush(); if (bufHead == bufEnd) { // tx is done state = TRANSMITTING_LAST; } } } } else if (state == TRANSMITTING_LAST) { state = TRANSMITTING_DONE; } else if (state == TRANSMITTING_DONE) { call RadioState.idle(); state = IDLE; // signal upper layer Tx done if (!post packet_sent()) { // try to post task first signal PhyComm.txPktDone(sendPtr); // signal directly if can't post } } return SUCCESS; } event result_t RadioByte.startSymDetected() { // Phy must be in IDLE state, otherwise there is a bug if (state == IDLE && recvBufState == FREE) { state = RECEIVING; recvCount = 0; // signal MAC w/ receiving buffer so that it can put in timestamp signal PhyComm.startSymDetected(recvPtr); return SUCCESS; } return FAIL; } event result_t RadioByte.rxByteDone(char data) { if (state == RECEIVING) { call Codec.decode(data); return SUCCESS; } return FAIL; }} // end of implementation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -