📄 fhp.c
字号:
// byte length
// The length of the packet in bytes.
// byte destination
// If the FHP is set up as slave, this argument has no effect as the
// packet is sent to the master anyway.
// If set up as master, the argument specifies the ID of the slave
// to receive the packet or BROADCASTID if all slaves should receive
// the packet.
//
// Return value:
// bool
// Returns TRUE if the previous transmission either has been
// successfully completed or canceled. Otherwise, FALSE is returned
// and the new packet is discarded.
//----------------------------------------------------------------------------
bool newSending(byte xdata* packet, byte length, byte destination) {
if (FHPstatus != IDLE)
return FALSE;
sendLength = length;
sendDest = destination;
sendPacket = packet;
FHPstatus = WAITING;
if (FHPmode != ACTIVE) {
errors = 99;
TIMER2_RUN(TRUE);
}
return TRUE;
} // end newSending
//----------------------------------------------------------------------------
// byte getSendStatus()
//
// Description:
// Used to check the status of the last initiated transmission.
//
// Arguments:
// None.
//
// Return value:
// byte
// The return value is one of:
// - IDLE if the last transmission is canceled or completed
// - NOLINK if this is a slave and
// there is no radio link with master
// - WAITING otherwise
//----------------------------------------------------------------------------
byte getSendStatus() {
return FHPstatus;
} // end getSendStatus
//----------------------------------------------------------------------------
// void cancelSending()
//
// Description:
// Cancels the current transmission. Thus, it will not be transmitted
// and a new transmission may be initiated.
//
// Arguments:
// None.
//
// Return value:
// void
//----------------------------------------------------------------------------
void cancelSending() {
FHPstatus = IDLE;
} // end cancelSending
//----------------------------------------------------------------------------
// bool synchronize()
//
// Description:
// Performs an acquisition by scanning through the frequency sequence.
//
// Arguments:
// None.
//
// Return value:
// bool
// TRUE if a stable connection was obtained, FALSE otherwise
//----------------------------------------------------------------------------
bool synchronize() {
byte i,hits=0,ptr0,ptr1;
bool turn = FALSE;
ulong time = getTime()/1000;
byte step = time/fhpSettings.period+1;
word wait = (word)(fhpSettings.period*(ulong)step-time);
// ET2 = 0; // disable timer 2
while (wait>255) {
halWait(255, fhpSettings.clkFreq);
wait-=255;
}
halWait(wait, fhpSettings.clkFreq);
if (fhpSettings.useLEDs) BLED = LED_ON;
ptr0 = lastKnownPosition+step;
ptr1 = lastKnownPosition+step+2;
for (i=1; i<=numberOfFrequencies; ++i) {
if (hits) {
changeFreq(RF_RX, 1);
++ptr0;
++ptr1;
--i;
} else {
//#define SIMPLE_STEPPING
#ifdef SIMPLE_STEPPING
changeFreq(RF_RX, 2);
#else
if (turn) {
if (ptr1>=numberOfFrequencies)
ptr1-=numberOfFrequencies;
setFrequencyPosition(ptr1);
ptr1 += 3;
} else {
if (ptr0>=numberOfFrequencies)
ptr0-=numberOfFrequencies;
setFrequencyPosition(ptr0++);
}
changeFreq(RF_RX,0);
turn = !turn;
#endif
}
if (listenForBeacon(fhpSettings.period/10)) {
++hits;
// require two hits in a row to avoid being fooled by interchannel noise
if (hits>=2) { //|| (GO_OFFLINE && !force)
changeFreq(RF_OFF, 1);
if (fhpSettings.useLEDs) BLED = LED_OFF;
ET2 = 1;
return TRUE;
}
} else {
hits = 0;
}
}
changeFreq(RF_OFF,0);
// ET2 = 1;
return FALSE;
} // end synchronize
//----------------------------------------------------------------------------
// void setMode(...)
//
// Description:
// Determines how active the FHP will be.
// If the FHP is set up as master, there are two alternatives:
// - OFF: The FHP is turned off and does nothing
// - ACTIVE: Beacons are transmitted periodically,
// packets from the slaves are received and
// any packets sent with newSending are transmitted.
// If the FHP is set up as slave, there are three alternatives:
// - OFF: The FHP is turned off and does nothing
// - PASSIVE: A timer is running in the background keeping track of
// where in the frequency sequence the master is.
// Packets sent with newSending are transmitted fast,
// but nothing is received (unless possibly when
// transmitting a packet itself).
// - ACTIVE: The FHP listens for every beacon transmitted by
// the master. Thus, the communication is full duplex.
//
// Arguments:
// byte mode
// One of OFF, PASSIVE or ACTIVE
//
// Return value:
// void
//----------------------------------------------------------------------------
void setMode(byte mode) {
byte oldMode = FHPmode;
if (isMaster && mode==PASSIVE)
mode = OFF; // Master has no PASSIVE mode
FHPmode = mode;
switch (mode) {
case OFF:
RTstop();
break;
case PASSIVE:
if (oldMode == OFF) {
RTstart();
}
if (FHPstatus == IDLE)
TIMER2_RUN(FALSE);
break;
case ACTIVE:
if (!isMaster) {
if (oldMode==OFF) {
RTstart();
}
}
errors = 99;
TIMER2_RUN(TRUE);
break;
default:
return; // error: undefined mode
}
} // end setMode
//----------------------------------------------------------------------------
// void setSystemID(...)
//
// Description:
// Sets the system ID. The master and all slaves that are to communicate
// with each other must have the same system ID. The reason is that
// all beacons and acknowledgements contain the system ID and are
// discarded if they do not match. Thus, giving systems different
// IDs prevents them from interfering with each other.
// All application programs should choose a system ID different from
// the default one, preferably chosen randomly for each particular system.
//
// Arguments:
// byte ID
// The new system ID. Range 0-127.
//
// Return value:
// void
//----------------------------------------------------------------------------
void setSystemID(byte ID) {
systemID = ID;
} // end setSystemID
//----------------------------------------------------------------------------
// void setOwnID(...)
//
// Description:
// If the FHP is set up as master, this function has no effect.
// Otherwise, it specifies the ID of the slave. The slave will only
// receive packets addressed to the BROADCASTID or to its own ID.
// The most significant bit in the ID must be 0, and the ID must not
// equal the BROADCASTID (0).
//
// Arguments:
// byte ID
// The new ID of the slave. Must be in the range 1-127.
//
// Return value:
// void
//----------------------------------------------------------------------------
void setOwnID(byte ID) {
srand(ID);
ownID = ID&~TRBIT;
} // end setOwnID
//----------------------------------------------------------------------------
// void fhpSlave()
//
// Description:
// Internal function only to be used by the FHP itself.
// Called periodically to listen for the beacons transmitted by the master.
// If the beacon is missed several times in a row, an acquisition is performed.
//
// Arguments:
// None.
//
// Return value:
// void
//----------------------------------------------------------------------------
void fhpSlave() {
if (errors >= 3) {
if (FHPstatus == WAITING)
FHPstatus = NOLINK;
while (!synchronize()) {
if (synchFailed!=NULL) {
TIMER2_RUN(FALSE);
synchFailed();
break;
}
}
} else {
changeFreq(RF_RX,0);
listenForBeacon(fhpSettings.listenTime);
changeFreq(RF_OFF, 1);
}
} // end slave
//----------------------------------------------------------------------------
// void fhpMaster()
//
// Description:
// Internal function only to be used by the FHP itself.
// Called periodically to send out beacons and any packets,
// and possibly receives packets from the slaves.
//
// Arguments:
// None.
//
// Return value:
// void
//----------------------------------------------------------------------------
void fhpMaster() {
byte length;
// Send beacon
changeFreq(RF_TX,0);
ctrl[0] = BEACON;
if (FHPstatus != IDLE) {
ctrl[1] = sendDest | TRBIT;
} else if (requester) {
ctrl[1] = requester;
} else {
ctrl[1] = BROADCASTID;
}
halRFSendPacket(PREAMBLE_BYTE_COUNT, &ctrl[0], 2);
if (ctrl[1]&TRBIT) {
// I will send something myself
fhpSendPacket();
} else if (requester) {
changeFreq(RF_RX, 0);
fhpReceivePacket(TRUE);
requester = 0;
} else {
changeFreq(RF_RX, 0);
length = halRFReceivePacket((fhpSettings.timeslots*fhpSettings.slotSize+9)/10, &ctrl[0], 2, 0, fhpSettings.clkFreq);
if (length==2 && ctrl[0]==systemID) {
requester = ctrl[1];
if (fhpSettings.useLEDs) GLED = LED_ON;
} else {
if (fhpSettings.useLEDs) RLED = LED_ON;
}
}
changeFreq(RF_OFF, 1);
if (fhpSettings.useLEDs) YLED = LED_OFF;
} //end master
//----------------------------------------------------------------------------
// void fhpJump() interrupt INUM_TIMER2
//
// Description:
// Internal function only to be used by the FHP itself.
// Interrupt service routine called periodically when in ACTIVE mode.
// Calls fhpMaster() or fhpSlave() depending on configuration.
//
// Arguments:
// None.
//
// Return value:
// void
//----------------------------------------------------------------------------
void fhpJump() interrupt INUM_TIMER2 {
INT_SETFLAG(INUM_TIMER2, INT_CLR);
if ( GO_OFFLINE ) {
TIMER2_RUN(FALSE);
return;
}
if (fhpSettings.useLEDs) {
GLED = LED_OFF;
RLED = LED_OFF;
YLED = LED_ON;
}
if (isMaster)
fhpMaster();
else
fhpSlave();
INT_SETFLAG(INUM_TIMER2, INT_CLR);
} // end jump
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -