📄 timesyncp.nc
字号:
tableEntries = 0; // don't reset table size unless you're recounting
numErrors = 0;
for(i = 0; i < MAX_ENTRIES; ++i) {
age = msg->localTime - table[i].localTime;
//logical time error compensation
if( age >= 0x7FFFFFFFL )
table[i].state = ENTRY_EMPTY;
if( table[i].state == ENTRY_EMPTY )
freeItem = i;
else
++tableEntries;
if( age >= oldestTime ) {
oldestTime = age;
oldestItem = i;
}
}
if( freeItem < 0 )
freeItem = oldestItem;
else
++tableEntries;
table[freeItem].state = ENTRY_FULL;
table[freeItem].localTime = msg->localTime;
table[freeItem].timeOffset = msg->globalTime - msg->localTime;
}
void task processMsg()
{
TimeSyncMsg* msg = (TimeSyncMsg*)(call Send.getPayload(processedMsg, sizeof(TimeSyncMsg)));
if( msg->rootID < outgoingMsg->rootID &&
// jw: after becoming the root ignore other roots messages (in send period)
~(heartBeats < IGNORE_ROOT_MSG && outgoingMsg->rootID == TOS_NODE_ID) ){
outgoingMsg->rootID = msg->rootID;
outgoingMsg->seqNum = msg->seqNum;
}
else if( outgoingMsg->rootID == msg->rootID && (int8_t)(msg->seqNum - outgoingMsg->seqNum) > 0 ) {
outgoingMsg->seqNum = msg->seqNum;
}
else
goto exit;
call Leds.led0Toggle();
if( outgoingMsg->rootID < TOS_NODE_ID )
heartBeats = 0;
addNewEntry(msg);
calculateConversion();
signal TimeSyncNotify.msg_received();
exit:
state &= ~STATE_PROCESSING;
}
event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
{
#ifdef TIMESYNC_DEBUG // this code can be used to simulate multiple hopsf
uint8_t incomingID = (uint8_t)((TimeSyncMsg*)payload)->nodeID;
int8_t diff = (incomingID & 0x0F) - (TOS_NODE_ID & 0x0F);
if( diff < -1 || diff > 1 )
return msg;
diff = (incomingID & 0xF0) - (TOS_NODE_ID & 0xF0);
if( diff < -16 || diff > 16 )
return msg;
#endif
if( (state & STATE_PROCESSING) == 0
&& call TimeSyncPacket.isValid(msg)) {
message_t* old = processedMsg;
processedMsg = msg;
((TimeSyncMsg*)(payload))->localTime = call TimeSyncPacket.eventTime(msg);
state |= STATE_PROCESSING;
post processMsg();
return old;
}
return msg;
}
task void sendMsg()
{
uint32_t localTime, globalTime;
globalTime = localTime = call GlobalTime.getLocalTime();
call GlobalTime.local2Global(&globalTime);
// we need to periodically update the reference point for the root
// to avoid wrapping the 32-bit (localTime - localAverage) value
if( outgoingMsg->rootID == TOS_NODE_ID ) {
if( (int32_t)(localTime - localAverage) >= 0x20000000 )
{
atomic
{
localAverage = localTime;
offsetAverage = globalTime - localTime;
}
}
}
else if( heartBeats >= ROOT_TIMEOUT ) {
heartBeats = 0; //to allow ROOT_SWITCH_IGNORE to work
outgoingMsg->rootID = TOS_NODE_ID;
++(outgoingMsg->seqNum); // maybe set it to zero?
}
outgoingMsg->globalTime = globalTime;
#ifdef LOW_POWER_LISTENING
call LowPowerListening.setRemoteWakeupInterval(&outgoingMsgBuffer, LPL_INTERVAL);
#endif
// we don't send time sync msg, if we don't have enough data
if( numEntries < ENTRY_SEND_LIMIT && outgoingMsg->rootID != TOS_NODE_ID ){
++heartBeats;
state &= ~STATE_SENDING;
}
else if( call Send.send(AM_BROADCAST_ADDR, &outgoingMsgBuffer, TIMESYNCMSG_LEN, localTime ) != SUCCESS ){
state &= ~STATE_SENDING;
signal TimeSyncNotify.msg_sent();
}
}
event void Send.sendDone(message_t* ptr, error_t error)
{
if (ptr != &outgoingMsgBuffer)
return;
if(error == SUCCESS)
{
++heartBeats;
call Leds.led1Toggle();
if( outgoingMsg->rootID == TOS_NODE_ID )
++(outgoingMsg->seqNum);
}
state &= ~STATE_SENDING;
signal TimeSyncNotify.msg_sent();
}
void timeSyncMsgSend()
{
if( outgoingMsg->rootID == 0xFFFF && ++heartBeats >= ROOT_TIMEOUT ) {
outgoingMsg->seqNum = 0;
outgoingMsg->rootID = TOS_NODE_ID;
}
if( outgoingMsg->rootID != 0xFFFF && (state & STATE_SENDING) == 0 ) {
state |= STATE_SENDING;
post sendMsg();
}
}
event void Timer.fired()
{
if (mode == TS_TIMER_MODE) {
timeSyncMsgSend();
}
else
call Timer.stop();
}
command error_t TimeSyncMode.setMode(uint8_t mode_){
if (mode_ == TS_TIMER_MODE){
call Timer.startPeriodic((uint32_t)(896U+(call Random.rand16()&0xFF)) * BEACON_RATE);
}
else
call Timer.stop();
mode = mode_;
return SUCCESS;
}
command uint8_t TimeSyncMode.getMode(){
return mode;
}
command error_t TimeSyncMode.send(){
if (mode == TS_USER_MODE){
timeSyncMsgSend();
return SUCCESS;
}
return FAIL;
}
command error_t Init.init()
{
atomic{
skew = 0.0;
localAverage = 0;
offsetAverage = 0;
};
clearTable();
atomic outgoingMsg = (TimeSyncMsg*)call Send.getPayload(&outgoingMsgBuffer, sizeof(TimeSyncMsg));
outgoingMsg->rootID = 0xFFFF;
processedMsg = &processedMsgBuffer;
state = STATE_INIT;
return SUCCESS;
}
event void Boot.booted()
{
call RadioControl.start();
call StdControl.start();
}
command error_t StdControl.start()
{
heartBeats = 0;
outgoingMsg->nodeID = TOS_NODE_ID;
call TimeSyncMode.setMode(TS_TIMER_MODE);
return SUCCESS;
}
command error_t StdControl.stop()
{
call Timer.stop();
return SUCCESS;
}
async command float TimeSyncInfo.getSkew() { return skew; }
async command uint32_t TimeSyncInfo.getOffset() { return offsetAverage; }
async command uint32_t TimeSyncInfo.getSyncPoint() { return localAverage; }
async command uint16_t TimeSyncInfo.getRootID() { return outgoingMsg->rootID; }
async command uint8_t TimeSyncInfo.getSeqNum() { return outgoingMsg->seqNum; }
async command uint8_t TimeSyncInfo.getNumEntries() { return numEntries; }
async command uint8_t TimeSyncInfo.getHeartBeats() { return heartBeats; }
default event void TimeSyncNotify.msg_received(){}
default event void TimeSyncNotify.msg_sent(){}
event void RadioControl.startDone(error_t error){}
event void RadioControl.stopDone(error_t error){}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -