X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fcc1000%2FCC1000SendReceiveP.nc;h=09a395501aa0d40869a485035d044ac9665e6d83;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=e4e4d77d9d95ac26eefc87d5682404fb74615e62;hpb=1a329382c4f4556fd52d85f4e3f4a67e54911682;p=tinyos-2.x.git diff --git a/tos/chips/cc1000/CC1000SendReceiveP.nc b/tos/chips/cc1000/CC1000SendReceiveP.nc index e4e4d77d..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,30 +49,46 @@ * @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; interface CC1000Control; interface HplCC1000Spi; - + 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, @@ -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) { @@ -632,13 +682,13 @@ implementation return TOSH_DATA_LENGTH; } - command void* Packet.getPayload(message_t *msg, uint8_t *len) { - if (len != NULL) { - cc1000_header_t *header = getHeader(msg); - - *len = header->length; + command void* Packet.getPayload(message_t *msg, uint8_t len) { + if (len <= TOSH_DATA_LENGTH) { + return (void* COUNT_NOK(len))msg->data; + } + else { + return NULL; } - return (void*)msg->data; } async command error_t PacketAcknowledgements.requestAck(message_t *msg) { @@ -649,27 +699,86 @@ implementation return FAIL; /* We always ack */ } - command void* Receive.getPayload(message_t *m, uint8_t *len) { + command uint8_t Send.maxPayloadLength() { + return call Packet.maxPayloadLength(); + } + + command void* Send.getPayload(message_t *m, uint8_t len) { return call Packet.getPayload(m, len); } - command uint8_t Receive.payloadLength(message_t *m) { - return call Packet.payloadLength(m); + async command bool PacketAcknowledgements.wasAcked(message_t *msg) { + return getMetadata(msg)->metadataBits & CC1000_ACK_BIT; + } + + async command bool LinkPacketMetadata.highChannelQuality(message_t* msg) { + return getMetadata(msg)->metadataBits & CC1000_WHITE_BIT; } - command uint8_t Send.maxPayloadLength() { - return call Packet.maxPayloadLength(); + /***************** PacketTimeStamp32khz Commands ****************/ + async command bool PacketTimeStamp32khz.isValid(message_t* msg) + { + return (getMetadata(msg)->timestamp != CC1000_INVALID_TIMESTAMP); } - command void* Send.getPayload(message_t *m) { - return call Packet.getPayload(m, NULL); + async command uint32_t PacketTimeStamp32khz.timestamp(message_t* msg) + { + return getMetadata(msg)->timestamp; } - async command bool PacketAcknowledgements.wasAcked(message_t *msg) { - return getMetadata(msg)->ack; + 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) { } }