xe1205phyp.nc

来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 412 行

NC
412
字号
/*  * Copyright (c) 2006, Ecole Polytechnique Federale de Lausanne (EPFL), * Switzerland. * 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 Ecole Polytechnique Federale de Lausanne (EPFL)  *   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. * * ======================================================================== *//* * @author Henri Dubois-Ferriere * */#include "Timer.h"module XE1205PhyP {  provides interface XE1205PhyRxTx;  provides interface Init @atleastonce();  provides interface SplitControl @atleastonce();  uses interface Resource as SpiResourceTX;  uses interface Resource as SpiResourceRX;  uses interface Resource as SpiResourceConfig;  uses interface XE1205PhySwitch;  uses interface XE1205IrqConf;  uses interface XE1205Fifo;  uses interface GpioInterrupt as Interrupt0;  uses interface GpioInterrupt as Interrupt1;  uses interface Alarm<T32khz,uint16_t> as Alarm32khz16;#if 0  uses interface GeneralIO as Dpin;#endif}implementation {#include "xe1205debug.h"  char* txBuf = NULL;  uint8_t rxFrameIndex = 0;  uint8_t rxFrameLen = 0;  uint8_t nextTxLen=0;  uint8_t nextRxLen;  char rxFrame[xe1205_mtu];  uint8_t headerLen = 4;  uint16_t stats_rxOverruns;  typedef enum {    RADIO_LISTEN=0,     RADIO_RX_HEADER=1,     RADIO_RX_PACKET=2,     RADIO_RX_PACKET_LAST=3,     RADIO_TX=4,    RADIO_SLEEP=5,     RADIO_STARTING=6  } phy_state_t;  phy_state_t state = RADIO_SLEEP;  void armPatternDetect();  command error_t Init.init()   { #if 0    call Dpin.makeOutput();#endif    call XE1205PhySwitch.sleepMode();    call XE1205PhySwitch.antennaOff();    return SUCCESS;  }  event void SpiResourceTX.granted() {  }  event void SpiResourceRX.granted() {  }  event void SpiResourceConfig.granted() {     armPatternDetect();    call SpiResourceConfig.release();    atomic {      call Interrupt0.enableRisingEdge();      state = RADIO_LISTEN;    }  }  task void startDone() {    signal SplitControl.startDone(SUCCESS);  }  task void stopDone() {    signal SplitControl.stopDone(SUCCESS);  }  command error_t SplitControl.start()   {    atomic state = RADIO_STARTING;    call XE1205PhySwitch.rxMode();    call XE1205PhySwitch.antennaRx();    call SpiResourceConfig.request();    post startDone();    return SUCCESS;  }  command error_t SplitControl.stop()   {    call XE1205PhySwitch.sleepMode();    call XE1205PhySwitch.antennaOff();    atomic state = RADIO_SLEEP;    post stopDone();    return SUCCESS;  }  default event void SplitControl.startDone(error_t error) { }  default event void SplitControl.stopDone(error_t error) { }  async command bool XE1205PhyRxTx.busy() {    atomic return state != RADIO_LISTEN; // xxx need to deal with sleep state  }  void armPatternDetect()   {    // small chance of a pattern arriving right after we arm,     // and IRQ0 hasn't been enabled yet, so we would miss the interrupt    // xxx maybe this can also be addressed with periodic timer?    xe1205check(2, call XE1205IrqConf.armPatternDetector(TRUE));    xe1205check(1, call XE1205IrqConf.clearFifoOverrun(TRUE));    }  async command void XE1205PhyRxTx.setRxHeaderLen(uint8_t l)   {    if (l > 8) l = 8;    if (!l) return;    headerLen = l;  }  async command uint8_t XE1205PhyRxTx.getRxHeaderLen() {    return headerLen;  }  void computeNextRxLength()   {    uint8_t n = rxFrameLen - rxFrameIndex;         // for timesync and such, we want the end of the packet to coincide with a fifofull event,     // so that we know precisely when last byte was received     if (n > 16) {      if (n < 32) nextRxLen = n - 16; else nextRxLen = 15;    }     else {      nextRxLen = n;    }  }  async command error_t XE1205PhyRxTx.sendFrame(char* data, uint8_t frameLen)  __attribute__ ((noinline))   {    error_t status;       if (frameLen < 6) return EINVAL;    atomic {      if (state == RADIO_SLEEP) return EOFF;      if (state != RADIO_LISTEN) return EBUSY;      if (frameLen == 0 || frameLen > xe1205_mtu + 7) return EINVAL; // 7 = 4 preamble + 3 sync            call XE1205PhySwitch.txMode(); // it takes 100us to switch from rx to tx, ie less than one byte at 76kbps      call Interrupt0.disable();      status = call SpiResourceTX.immediateRequest();      xe1205check(3, status);      if (status != SUCCESS) {	call XE1205PhySwitch.rxMode(); 	call SpiResourceConfig.request();	return status;      }      call XE1205PhySwitch.antennaTx();      state = RADIO_TX;    }    status = call XE1205Fifo.write(data, frameLen);    // cannot happen with current SPI implementation (at least with NoDma)#if 0    if (status != SUCCESS) {      xe1205error(8, status);      call XE1205PhySwitch.rxMode();       call XE1205PhySwitch.antennaRx();      armPatternDetect();      call SpiResourceTX.release();      atomic {	call Interrupt0.enableRisingEdge();	state = RADIO_LISTEN;      }      return status;    }#endif    return SUCCESS;  }  uint16_t rxByte=0;  /**   * In transmit: nTxFifoEmpty. (ie after the last byte has been *read out of the fifo*)   * In receive: write_byte.    */  async event void Interrupt0.fired()  __attribute__ ((noinline))   {     error_t status;    switch (state) {    case RADIO_LISTEN:      rxByte=1;      state = RADIO_RX_HEADER;      status = call SpiResourceRX.immediateRequest();      xe1205check(4, status);      if (status != SUCCESS) {	state = RADIO_LISTEN;	call Interrupt0.disable(); // because pattern detector won't be rearmed right away	call SpiResourceConfig.request();	return;      }      return;    case RADIO_RX_HEADER:      rxByte++;      if (rxByte == 2) {	call Alarm32khz16.start(3000);      }      if (rxByte == headerLen + 1) {	call Interrupt0.disable();	xe1205check(8, call XE1205Fifo.read(rxFrame, headerLen));	call Interrupt1.enableRisingEdge();      }      return;    case RADIO_TX:      call Interrupt0.disable(); // avoid spurious IRQ0s from nTxFifoEmpty rebounding briefly after first byte is written.                                 // note that we should really wait till writedone() to re-enable either interrupt.      xe1205check(5, call XE1205Fifo.write(txBuf, nextTxLen));      return;    default:      return;    }  }  bool reading=FALSE;  /**   * In transmit: TxStopped. (ie after the last byte has been *sent*)   * In receive: Fifofull.   */  async event void Interrupt1.fired()  __attribute__ ((noinline))   {     switch (state) {    case RADIO_RX_PACKET:      reading = TRUE;      xe1205check(9, call XE1205Fifo.read(&rxFrame[rxFrameIndex], nextRxLen));      call Interrupt1.disable(); // in case it briefly goes back to full just after we read first byte      rxFrameIndex += nextRxLen;      computeNextRxLength();            if (nextRxLen==0) {	state = RADIO_RX_PACKET_LAST;      }      return;    case RADIO_RX_HEADER: // somehow the FIFO has filled before we finished reading the header bytes      call Interrupt1.disable();      call Alarm32khz16.stop();      signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);      armPatternDetect();      call SpiResourceRX.release();      atomic {	call Interrupt0.enableRisingEdge();	state = RADIO_LISTEN;      }      return;    case RADIO_TX:      call Interrupt1.disable();      call XE1205PhySwitch.rxMode();       call XE1205PhySwitch.antennaRx();      signal XE1205PhyRxTx.sendFrameDone();      armPatternDetect();      call SpiResourceTX.release();      atomic {	call Interrupt0.enableRisingEdge();	state = RADIO_LISTEN;      }      return;    default:      return;    }  }  async event void XE1205Fifo.readDone(error_t error) {    xe1205check(6, error);    switch(state) {    case RADIO_RX_HEADER:      rxFrameLen = signal XE1205PhyRxTx.rxFrameBegin(rxFrame, headerLen);      if (rxFrameLen <= headerLen) {	call Interrupt1.disable();	call Alarm32khz16.stop();	signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);	armPatternDetect();	call SpiResourceRX.release();	atomic {	  call Interrupt0.enableRisingEdge();	  state = RADIO_LISTEN;	}	return;      }      rxFrameIndex = headerLen;      computeNextRxLength();      state = RADIO_RX_PACKET;      return;    case RADIO_RX_PACKET_LAST:      call Alarm32khz16.stop();      signal XE1205PhyRxTx.rxFrameEnd(rxFrame, rxFrameLen + headerLen, SUCCESS);      armPatternDetect();       call SpiResourceRX.release();      atomic {	call Interrupt0.enableRisingEdge();	state = RADIO_LISTEN;      }      return;    case RADIO_RX_PACKET:      reading = FALSE;      call Interrupt1.enableRisingEdge();      return;    default:      xe1205check(10, FAIL);      return;    }  }  async event void XE1205Fifo.writeDone(error_t error)  __attribute__ ((noinline)) {     xe1205check(7, error);    switch(state) {    case RADIO_TX:      txBuf = signal XE1205PhyRxTx.continueSend(&nextTxLen);      if (nextTxLen) {	call Interrupt0.enableFallingEdge();      } else {	call Interrupt0.disable();	call Interrupt1.enableRisingEdge();      }      return;    default:      xe1205check(11, FAIL);    }  }  async event void Alarm32khz16.fired() {    stats_rxOverruns++;    signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);    armPatternDetect();     call SpiResourceRX.release();    atomic {      call Interrupt0.enableRisingEdge();      state = RADIO_LISTEN;    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?