]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc1000/CC1000SendReceiveP.nc
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / chips / cc1000 / CC1000SendReceiveP.nc
index 31a2fc2c634a255efabffcdecf1221b778ebb62c..09a395501aa0d40869a485035d044ac9665e6d83 100644 (file)
@@ -1,6 +1,4 @@
-// $Id$
-
-/*                                                                     tab:4
+/*
  * "Copyright (c) 2000-2005 The Regents of the University  of California.  
  * All rights reserved.
  *
@@ -32,6 +30,7 @@
 #include "crc.h"
 #include "CC1000Const.h"
 #include "Timer.h"
+#include "CC1000TimeSyncMessage.h"
 
 /**
  * A rewrite of the low-power-listening CC1000 radio stack.
  * @author Jaein Jeong
  * @author Joe Polastre
  * @author David Gay
+ * @author Marco Langerwisch (Packet timestamping)
  */
   
-module CC1000SendReceiveP {
+module CC1000SendReceiveP @safe() {
   provides {
     interface Init;
     interface StdControl;
     interface Send;
     interface Receive;
-    interface RadioTimeStamping;
     interface Packet;
     interface ByteRadio;
     interface PacketAcknowledgements;
+    interface LinkPacketMetadata;
+
+    interface PacketTimeStamp<T32khz, uint32_t> as PacketTimeStamp32khz;
+    interface PacketTimeStamp<TMilli, uint32_t> as PacketTimeStampMilli;
+    interface PacketTimeSyncOffset;
   }
   uses {
     //interface PowerManagement;
     interface CC1000Control;
     interface HplCC1000Spi;
-
+    interface CC1000Squelch;
     interface ReadNow<uint16_t> as RssiRx;
     async command am_addr_t amAddress();
+
+    interface LocalTime<T32khz> as LocalTime32khz;
+    interface LocalTime<TMilli> as LocalTimeMilli;
   }
 }
 implementation 
 {
+#ifdef PLATFORM_MICA2
+  // estimated calibration, 19.2 Kbps data, Manchester Encoding, time in jiffies (32768 Hz)
+  static const int8_t BIT_CORRECTION[8] = { 27, 28, 30, 32, 34, 36, 38, 40 };
+#else
+  // other platforms not calibrated yet
+  static const uint8_t BIT_CORRECTION[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
   enum {
     OFF_STATE,
 
@@ -121,26 +136,26 @@ implementation
 
   uint16_t rxShiftBuf;
   message_t rxBuf;
-  message_t *rxBufPtr = &rxBuf;
+  message_t * ONE rxBufPtr = &rxBuf;
 
   uint16_t preambleLength;
-  message_t *txBufPtr;
+  message_t * ONE_NOK txBufPtr;
   uint8_t nextTxByte;
 
   const_uint8_t ackCode[5] = { 0xab, ACK_BYTE1, ACK_BYTE2, 0xaa, 0xaa };
 
   /* Packet structure accessor functions. Note that everything is
    * relative to the data field. */
-  cc1000_header_t *getHeader(message_t *amsg) {
-    return (cc1000_header_t *)(amsg->data - sizeof(cc1000_header_t));
+  cc1000_header_t * ONE getHeader(message_t * ONE amsg) {
+    return TCAST(cc1000_header_t * ONE, (uint8_t *)amsg + offsetof(message_t, data) - sizeof(cc1000_header_t));
   }
 
-  cc1000_footer_t *getFooter(message_t *amsg) {
+  cc1000_footer_t *getFooter(message_t * ONE amsg) {
     return (cc1000_footer_t *)(amsg->footer);
   }
   
-  cc1000_metadata_t *getMetadata(message_t *amsg) {
-    return (cc1000_metadata_t *)((uint8_t *)amsg->footer + sizeof(cc1000_footer_t));
+  cc1000_metadata_t * ONE getMetadata(message_t * ONE amsg) {
+    return TCAST(cc1000_metadata_t * ONE, (uint8_t *)amsg + offsetof(message_t, footer) + sizeof(cc1000_footer_t));
   }
   
   /* State transition functions */
@@ -256,10 +271,14 @@ implementation
          return FAIL;
        else {
          cc1000_header_t *header = getHeader(msg);
+          cc1000_metadata_t *metadata = getMetadata(msg);
 
          f.txBusy = TRUE;
          header->length = len;
          txBufPtr = msg;
+
+          metadata->timesync = FALSE;
+          metadata->timestamp = CC1000_INVALID_TIMESTAMP;
        }
       }
     signal ByteRadio.rts(msg);
@@ -298,12 +317,23 @@ implementation
     sendNextByte();
     nextTxByte = SYNC_BYTE2;
     enterTxDataState();
-    signal RadioTimeStamping.transmittedSFD(0, txBufPtr); 
   }
 
   void txData() {
     cc1000_header_t *txHeader = getHeader(txBufPtr);
     sendNextByte();
+
+    if (nextTxByte == SYNC_BYTE2) {
+      // SYNC_WORD has just been sent
+      uint32_t time32khz = call LocalTime32khz.get();
+      call PacketTimeStamp32khz.set(txBufPtr, time32khz);
+
+      if (call PacketTimeSyncOffset.isSet(txBufPtr)) {
+        timesync_radio_t *timesync = (timesync_radio_t*)((void*)txBufPtr + call PacketTimeSyncOffset.get(txBufPtr));
+        // set timesync event time as the offset between the event time and the SFD interrupt time (TEP 133)
+        *timesync  -= time32khz;
+      }
+    }
     
     if (count < txHeader->length + sizeof(message_header_t))
       {
@@ -361,14 +391,14 @@ implementation
 
        if (rxShiftBuf == ACK_WORD)
          {
-           getMetadata(txBufPtr)->ack = 1;
+           getMetadata(txBufPtr)->metadataBits |= CC1000_ACK_BIT;
            enterTxDoneState();
            return;
          }
       }
     if (count >= MAX_ACK_WAIT)
       {
-       getMetadata(txBufPtr)->ack = 0;
+       getMetadata(txBufPtr)->metadataBits &= ~CC1000_ACK_BIT;
        enterTxDoneState();
       }
   }
@@ -444,9 +474,12 @@ implementation
     else if (count <= 6)
       {
        // TODO: Modify to be tolerant of bad bits in the preamble...
+        uint32_t time;
        uint16_t tmp;
        uint8_t i;
 
+        time = call LocalTime32khz.get();
+
        // bit shift the data in with previous sample to find sync
        tmp = rxShiftBuf;
        rxShiftBuf = rxShiftBuf << 8 | in;
@@ -463,7 +496,10 @@ implementation
                enterRxState();
                signal ByteRadio.rx();
                f.rxBitOffset = 7 - i;
-               signal RadioTimeStamping.receivedSFD(0);
+                // correct receive time according to bit offset and set timestamp
+                time -= BIT_CORRECTION[f.rxBitOffset];
+                call PacketTimeStamp32khz.set(rxBufPtr, time);
+
                call RssiRx.read();
              }
          }
@@ -497,7 +533,7 @@ implementation
 
     rxShiftBuf = rxShiftBuf << 8 | in;
     nextByte = rxShiftBuf >> f.rxBitOffset;
-    ((uint8_t *)rxBufPtr)[count++] = nextByte;
+    ((uint8_t *COUNT(sizeof(message_t)))rxBufPtr)[count++] = nextByte;
 
     // Adjust rxLength to correspond to the corresponding offset in message_t
     rxLength += offsetof(message_t, data);
@@ -567,6 +603,18 @@ implementation
   }
 
   void packetReceiveDone() {
+    uint16_t snr;
+
+    snr = (uint16_t) getMetadata(rxBufPtr)->strength_or_preamble;
+    /* Higher signal strengths have lower voltages. So see if we're
+       CC1000_WHITE_BIT_THRESH *below* the noise floor. */
+    if ((snr + CC1000_WHITE_BIT_THRESH) < ((call CC1000Squelch.get()))) {
+      getMetadata(rxBufPtr)->metadataBits |= CC1000_WHITE_BIT;
+    }
+    else {
+      getMetadata(rxBufPtr)->metadataBits &= ~CC1000_WHITE_BIT;
+    }
+    
     post signalPacketReceived();
     enterReceivedState();
   }
@@ -616,7 +664,9 @@ implementation
   /* Abstract packet layout */
 
   command void Packet.clear(message_t *msg) {
-    memset(msg, 0, sizeof(message_t));
+    memset(getHeader(msg), 0x0, sizeof(cc1000_header_t));
+    memset(getFooter(msg), 0x0, sizeof(cc1000_footer_t));
+    memset(getMetadata(msg), 0x0, sizeof(cc1000_metadata_t));
   }
 
   command uint8_t Packet.payloadLength(message_t *msg) {
@@ -634,7 +684,7 @@ implementation
 
   command void* Packet.getPayload(message_t *msg, uint8_t len) {
     if (len <= TOSH_DATA_LENGTH) {
-      return (void*)msg->data;
+      return (void* COUNT_NOK(len))msg->data;
     }
     else {
       return NULL;
@@ -658,10 +708,77 @@ implementation
   }
 
   async command bool PacketAcknowledgements.wasAcked(message_t *msg) {
-    return getMetadata(msg)->ack;
+    return getMetadata(msg)->metadataBits & CC1000_ACK_BIT;
+  }
+
+  async command bool LinkPacketMetadata.highChannelQuality(message_t* msg) {
+    return getMetadata(msg)->metadataBits & CC1000_WHITE_BIT;
+  }
+
+  /***************** PacketTimeStamp32khz Commands ****************/
+  async command bool PacketTimeStamp32khz.isValid(message_t* msg)
+  {
+    return (getMetadata(msg)->timestamp != CC1000_INVALID_TIMESTAMP);
+  }
+
+  async command uint32_t PacketTimeStamp32khz.timestamp(message_t* msg)
+  {
+    return getMetadata(msg)->timestamp;
+  }
+
+  async command void PacketTimeStamp32khz.clear(message_t* msg)
+  {
+    getMetadata(msg)->timesync = FALSE;
+    getMetadata(msg)->timestamp = CC1000_INVALID_TIMESTAMP;
+  }
+
+  async command void PacketTimeStamp32khz.set(message_t* msg, uint32_t value)
+  {
+    getMetadata(msg)->timestamp = value;
+  }
+
+  /***************** PacketTimeStampMilli Commands ****************/
+  // over the air value is always T32khz
+  async command bool PacketTimeStampMilli.isValid(message_t* msg)
+  {
+    return call PacketTimeStamp32khz.isValid(msg);
+  }
+
+  async command uint32_t PacketTimeStampMilli.timestamp(message_t* msg)
+  {
+    int32_t offset = call PacketTimeStamp32khz.timestamp(msg) - call LocalTime32khz.get();
+    return (offset >> 5) + call LocalTimeMilli.get();
+  }
+
+  async command void PacketTimeStampMilli.clear(message_t* msg)
+  {
+    call PacketTimeStamp32khz.clear(msg);
+  }
+
+  async command void PacketTimeStampMilli.set(message_t* msg, uint32_t value)
+  {
+    int32_t offset = (value - call LocalTimeMilli.get()) << 5;
+    call PacketTimeStamp32khz.set(msg, offset + call LocalTime32khz.get());
+  }
+
+  /*----------------- PacketTimeSyncOffset -----------------*/
+  async command bool PacketTimeSyncOffset.isSet(message_t* msg)
+  {
+    return getMetadata(msg)->timesync;
+  }
+
+  async command uint8_t PacketTimeSyncOffset.get(message_t* msg)
+  {
+    return sizeof(cc1000_header_t) + getHeader(msg)->length - sizeof(timesync_radio_t);
+  }
+
+  async command void PacketTimeSyncOffset.set(message_t* msg)
+  {
+    getMetadata(msg)->timesync = TRUE;
+  }
+
+  async command void PacketTimeSyncOffset.cancel(message_t* msg)
+  {
+    getMetadata(msg)->timesync = FALSE;
   }
-  // Default events for radio send/receive coordinators do nothing.
-  // Be very careful using these, or you'll break the stack.
-  default async event void RadioTimeStamping.transmittedSFD(uint16_t time, message_t *msgBuff) { }
-  default async event void RadioTimeStamping.receivedSFD(uint16_t time) { }
 }