+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Arch Rock Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
-\r
-/**\r
- * @author Jonathan Hui <jhui@archrock.com>\r
- * @version $Revision$ $Date$\r
- */\r
-\r
-module CC2420ReceiveP {\r
-\r
- provides interface Init;\r
- provides interface AsyncStdControl;\r
- provides interface CC2420Receive;\r
- provides interface Receive;\r
-\r
- uses interface GeneralIO as CSN;\r
- uses interface GeneralIO as FIFO;\r
- uses interface GeneralIO as FIFOP;\r
- uses interface GpioInterrupt as InterruptFIFOP;\r
-\r
- uses interface Resource as SpiResource;\r
- uses interface CC2420Fifo as RXFIFO;\r
- uses interface CC2420Strobe as SACK;\r
- uses interface CC2420Strobe as SFLUSHRX;\r
-\r
- uses interface Leds;\r
-\r
-}\r
-\r
-implementation {\r
-\r
- typedef enum {\r
- S_STOPPED,\r
- S_STARTED,\r
- S_RX_HEADER,\r
- S_RX_PAYLOAD,\r
- } cc2420_receive_state_t;\r
-\r
- enum {\r
- RXFIFO_SIZE = 128,\r
- TIMESTAMP_QUEUE_SIZE = 8,\r
- };\r
-\r
- uint16_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];\r
- uint8_t m_timestamp_head, m_timestamp_size;\r
- uint8_t m_missed_packets;\r
-\r
- bool fallingEdgeEnabled;\r
- \r
- norace uint8_t m_bytes_left;\r
- norace message_t* m_p_rx_buf;\r
-\r
- message_t m_rx_buf;\r
- cc2420_receive_state_t m_state;\r
-\r
- void beginReceive();\r
- void receive();\r
- void waitForNextPacket();\r
- task void receiveDone_task();\r
-\r
- cc2420_header_t* getHeader( message_t* msg ) {\r
- return (cc2420_header_t*)( msg->data - sizeof( cc2420_header_t ) );\r
- }\r
- \r
- cc2420_metadata_t* getMetadata( message_t* msg ) {\r
- return (cc2420_metadata_t*)msg->metadata;\r
- }\r
- \r
- command error_t Init.init() {\r
- fallingEdgeEnabled = FALSE;\r
- m_p_rx_buf = &m_rx_buf;\r
- return SUCCESS;\r
- }\r
-\r
- void reset_state() {\r
- m_bytes_left = RXFIFO_SIZE;\r
- m_timestamp_head = m_timestamp_size = 0;\r
- m_missed_packets = 0;\r
- }\r
-\r
- async command error_t AsyncStdControl.start() {\r
- atomic {\r
- reset_state();\r
- m_state = S_STARTED;\r
- \r
- // MicaZ's don't like to re-enable the falling edge\r
- if(!fallingEdgeEnabled) {\r
- call InterruptFIFOP.enableFallingEdge();\r
- fallingEdgeEnabled = TRUE;\r
- }\r
- }\r
- return SUCCESS;\r
- }\r
-\r
- async command error_t AsyncStdControl.stop() {\r
- atomic {\r
- m_state = S_STOPPED;\r
- // MicaZ's don't like to re-enable the falling edge\r
- //call InterruptFIFOP.disable();\r
- }\r
- return SUCCESS;\r
- }\r
-\r
- async command void CC2420Receive.sfd( uint16_t time ) {\r
- if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {\r
- uint8_t tail = ( ( m_timestamp_head + m_timestamp_size ) % \r
- TIMESTAMP_QUEUE_SIZE );\r
- m_timestamp_queue[ tail ] = time;\r
- m_timestamp_size++;\r
- }\r
- }\r
-\r
- async command void CC2420Receive.sfd_dropped() {\r
- if ( m_timestamp_size )\r
- m_timestamp_size--;\r
- }\r
-\r
- async event void InterruptFIFOP.fired() {\r
- if ( m_state == S_STARTED )\r
- beginReceive();\r
- else\r
- m_missed_packets++;\r
- }\r
- \r
- void beginReceive() { \r
- m_state = S_RX_HEADER;\r
- if ( call SpiResource.immediateRequest() == SUCCESS )\r
- receive();\r
- else\r
- call SpiResource.request();\r
- }\r
- \r
- event void SpiResource.granted() {\r
- receive();\r
- }\r
-\r
- void receive() {\r
- call CSN.clr();\r
- call RXFIFO.beginRead( (uint8_t*)getHeader( m_p_rx_buf ), 1 );\r
- }\r
-\r
- async event void RXFIFO.readDone( uint8_t* rx_buf, uint8_t rx_len,\r
- error_t error ) {\r
-\r
- cc2420_header_t* header = getHeader( m_p_rx_buf );\r
- cc2420_metadata_t* metadata = getMetadata( m_p_rx_buf );\r
- uint8_t* buf = (uint8_t*)header;\r
- uint8_t length = buf[ 0 ];\r
-\r
- switch( m_state ) {\r
-\r
- case S_RX_HEADER:\r
- m_state = S_RX_PAYLOAD;\r
- if ( length + 1 > m_bytes_left ) {\r
- reset_state();\r
- call CSN.set();\r
- call CSN.clr();\r
- call SFLUSHRX.strobe();\r
- call SFLUSHRX.strobe();\r
- call CSN.set();\r
- call SpiResource.release();\r
- waitForNextPacket();\r
- }\r
- else {\r
- if ( !call FIFO.get() && !call FIFOP.get() )\r
- m_bytes_left -= length + 1;\r
- call RXFIFO.continueRead( (length <= MAC_PACKET_SIZE) ? buf + 1 : NULL,\r
- length );\r
- }\r
- break;\r
- \r
- case S_RX_PAYLOAD:\r
- \r
- call CSN.set();\r
- call SpiResource.release();\r
- \r
- if ( m_timestamp_size ) {\r
- if ( length > 10 ) {\r
- metadata->time = m_timestamp_queue[ m_timestamp_head ];\r
- m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;\r
- m_timestamp_size--;\r
- }\r
- }\r
- else {\r
- metadata->time = 0xffff;\r
- }\r
- \r
- // pass packet up if crc is good\r
- if ( ( buf[ length ] >> 7 ) && rx_buf ) {\r
- uint8_t type = ( header->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7;\r
- signal CC2420Receive.receive( type, m_p_rx_buf );\r
- if ( type == IEEE154_TYPE_DATA ) {\r
- post receiveDone_task();\r
- return;\r
- }\r
- }\r
- \r
- waitForNextPacket();\r
- break;\r
-\r
- default:\r
- call CSN.set();\r
- call SpiResource.release();\r
- break;\r
- \r
- }\r
- \r
- }\r
-\r
- task void receiveDone_task() {\r
- \r
- cc2420_header_t* header = getHeader( m_p_rx_buf );\r
- cc2420_metadata_t* metadata = getMetadata( m_p_rx_buf );\r
- uint8_t* buf = (uint8_t*)header;\r
- uint8_t length = buf[ 0 ];\r
- \r
- metadata->crc = buf[ length ] >> 7;\r
- metadata->rssi = buf[ length - 1 ];\r
- metadata->lqi = buf[ length ] & 0x7f;\r
- m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data, \r
- length );\r
-\r
- waitForNextPacket();\r
-\r
- }\r
-\r
- void waitForNextPacket() {\r
-\r
- atomic {\r
- if ( m_state == S_STOPPED )\r
- return;\r
-\r
- if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() ) {\r
- if ( m_missed_packets )\r
- m_missed_packets--;\r
- beginReceive();\r
- }\r
- else {\r
- m_state = S_STARTED;\r
- m_missed_packets = 0;\r
- }\r
- } \r
- \r
- }\r
-\r
- command void* Receive.getPayload(message_t* m, uint8_t* len) {\r
- if (len != NULL) {\r
- *len = TOSH_DATA_LENGTH;\r
- }\r
- return m->data;\r
- }\r
-\r
- command uint8_t Receive.payloadLength(message_t* m) {\r
- uint8_t* buf = (uint8_t*)getHeader( m_p_rx_buf );\r
- return buf[0];\r
- }\r
-\r
- async event void RXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error ) {} \r
-}\r