X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fcc1000%2FCC1000SendReceiveP.nc;h=09a395501aa0d40869a485035d044ac9665e6d83;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=a4aec3989936334a092b3ae7dd5f1ccc412a8421;hpb=4f1261f39f507f2044ae702a6f93316dcc56360e;p=tinyos-2.x.git diff --git a/tos/chips/cc1000/CC1000SendReceiveP.nc b/tos/chips/cc1000/CC1000SendReceiveP.nc index a4aec398..09a39550 100644 --- a/tos/chips/cc1000/CC1000SendReceiveP.nc +++ b/tos/chips/cc1000/CC1000SendReceiveP.nc @@ -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. @@ -50,19 +49,23 @@ * @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 as PacketTimeStamp32khz; + interface PacketTimeStamp as PacketTimeStampMilli; + interface PacketTimeSyncOffset; } uses { //interface PowerManagement; @@ -71,10 +74,21 @@ module CC1000SendReceiveP { interface CC1000Squelch; interface ReadNow as RssiRx; async command am_addr_t amAddress(); + + interface LocalTime as LocalTime32khz; + interface LocalTime 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, @@ -122,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 */ @@ -257,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); @@ -299,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)) { @@ -445,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; @@ -464,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(); } } @@ -498,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); @@ -568,22 +603,16 @@ implementation } void packetReceiveDone() { - message_t* pBuf; uint16_t snr; - atomic { - if (radioState != RECEIVED_STATE) { - return; - } - pBuf = rxBufPtr; - } - snr = (uint16_t) getMetadata(pBuf)->strength_or_preamble; + + 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(pBuf)->metadataBits |= CC1000_WHITE_BIT; + getMetadata(rxBufPtr)->metadataBits |= CC1000_WHITE_BIT; } else { - getMetadata(pBuf)->metadataBits &= ~CC1000_WHITE_BIT; + getMetadata(rxBufPtr)->metadataBits &= ~CC1000_WHITE_BIT; } post signalPacketReceived(); @@ -635,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) { @@ -653,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; @@ -683,9 +714,71 @@ implementation async command bool LinkPacketMetadata.highChannelQuality(message_t* msg) { return getMetadata(msg)->metadataBits & CC1000_WHITE_BIT; } - - // 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) { } + + /***************** 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; + } }