📄 mac_csp_tx.c
字号:
*/
RFST = SKIP(2+__SNOP_SKIP__, C_SFD_IS_INACTIVE);
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECY;
RFST = __SNOP__;
/*
* Watch the SFD pin to determine when the transmit has finished going out.
* The INT instruction causes an interrupt to fire. The ISR for this interrupt
* handles the record the timestamp (which was just captured when SFD went high).
* Decrement CSPZ at the last step to indicate transmit was successful.
*/
RFST = WHILE(C_SFD_IS_INACTIVE);
RFST = INT;
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECZ;
}
/**************************************************************************************************
* @fn macCspTxPrepCsmaSlotted
*
* @brief Prepare CSP for "Slotted CSMA" transmit. Load CSP program and set CSP parameters.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxPrepCsmaSlotted(void)
{
cspPrepForTxProgram();
/*----------------------------------------------------------------------
* Load CSP program : Slotted CSMA transmit
*/
/* wait for X number of backoffs */
RFST = WAITX;
/* wait for one backoff to guarantee receiver has been on at least that long */
RFST = WAITW(1);
/* sample CCA, if it fails exit from here, CSPZ indicates result */
RFST = SKIP(1+__SNOP_SKIP__, C_CCA_IS_VALID);
RFST = SSTOP;
RFST = __SNOP__;
/* per CSMA in specification, wait one backoff */
RFST = WAITW(1);
/* sample CCA again, if it fails exit from here, CSPZ indicates result */
RFST = SKIP(1+__SNOP_SKIP__, C_CCA_IS_VALID);
RFST = SSTOP;
RFST = __SNOP__;
/* CSMA has passed so transmit */
RFST = STXON;
/*
* If the SFD pin is high at this point, there was an RX-TX collision.
* In other words, TXON was strobed while receiving. The CSP variable
* CSPY is decremented to indicate this happened. The rest of the transmit
* continues normally.
*/
RFST = SKIP(2+__SNOP_SKIP__, C_SFD_IS_INACTIVE);
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECY;
RFST = __SNOP__;
/*
* Watch the SFD pin to determine when the transmit has finished going out.
* The INT instruction causes an interrupt to fire. The ISR for this interrupt
* handles the record the timestamp (which was just captured when SFD went high).
* Decrement CSPZ at the last step to indicate transmit was successful.
*/
RFST = WHILE(C_SFD_IS_INACTIVE);
RFST = INT;
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECZ;
}
/**************************************************************************************************
* @fn macCspTxGoCsma
*
* @brief Run previously loaded CSP program for CSMA transmit. Handles either
* slotted or unslotted CSMA transmits. When CSP program has finished,
* an interrupt occurs and macCspTxStopIsr() is called. This ISR will in
* turn call macTxDoneCallback().
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxGoCsma(void)
{
/*
* Set CSPX with the countdown time of the CSMA delay. Subtract one because there is
* a built-in one backoff delay in the CSP program to make sure receiver has been 'on'
* for at least one backoff. Don't subtract though if CSPX is already zero!
*/
CSPX = macTxCsmaBackoffDelay;
if (CSPX != 0)
{
CSPX--;
}
/*
* Set WEVENT to trigger at the current value of the timer. This allows
* unslotted CSMA to transmit just a little bit sooner.
*/
CSP_WEVENT_SET_TRIGGER_NOW();
/*
* Enable interrupt that fires when CSP program stops.
* Also enable interrupt that fires when INT instruction
* is executed.
*/
MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
MAC_MCU_CSP_INT_ENABLE_INTERRUPT();
/*
* Turn on the receiver if it is not already on. Receiver must be 'on' for at
* least one backoff before performing clear channel assessment (CCA).
*/
macRxOn();
/* start the CSP program */
CSP_START_PROGRAM();
}
/**************************************************************************************************
* @fn macCspTxPrepSlotted
*
* @brief Prepare CSP for "Slotted" (non-CSMA) transmit.
* Load CSP program and set CSP parameters.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxPrepSlotted(void)
{
cspPrepForTxProgram();
/*----------------------------------------------------------------------
* Load CSP program : Slotted transmit (no CSMA)
*/
/* wait for X number of backoffs */
RFST = WAITX;
/* just transmit, no CSMA required */
RFST = STXON;
/*
* If the SFD pin is high at this point, there was an RX-TX collision.
* In other words, TXON was strobed while receiving. The CSP variable
* CSPY is decremented to indicate this happened. The rest of the transmit
* continues normally.
*/
RFST = SKIP(2+__SNOP_SKIP__, C_SFD_IS_INACTIVE);
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECY;
RFST = __SNOP__;
/*
* Watch the SFD pin to determine when the transmit has finished going out.
* The INT instruction causes an interrupt to fire. The ISR for this interrupt
* handles the record the timestamp (which was just captured when SFD went high).
* Decrement CSPZ at the last step to indicate transmit was successful.
*/
RFST = WHILE(C_SFD_IS_INACTIVE);
RFST = INT;
RFST = WHILE(C_SFD_IS_ACTIVE);
RFST = DECZ;
}
/**************************************************************************************************
* @fn macCspTxGoSlotted
*
* @brief Run previously loaded CSP program for non-CSMA slotted transmit. When CSP
* program has finished, an interrupt occurs and macCspTxStopIsr() is called.
* This ISR will in turn call macTxDoneCallback().
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxGoSlotted(void)
{
halIntState_t s;
uint8 lowByteOfBackoffCount;
uint8 backoffCountdown;
/*
* Enable interrupt that fires when CSP program stops.
* Also enable interrupt that fires when INT instruction
* is executed.
*/
MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
MAC_MCU_CSP_INT_ENABLE_INTERRUPT();
/* critical section needed for timer accesses */
HAL_ENTER_CRITICAL_SECTION(s);
/* store lowest byte of backoff count (same as lowest byte of overflow count) */
lowByteOfBackoffCount = T2OF0;
/*
* Compute the number of backoffs until time to strobe transmit. The strobe should
* occur one backoff before the SFD pin is expected to go high. So, the forumla for the
* countdown value is to determine when the lower bits would rollover and become zero,
* and then subtract one.
*/
backoffCountdown = SLOTTED_TX_MAX_BACKOFF_COUNTDOWN - (lowByteOfBackoffCount & SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK) - 1;
/*
* Store backoff countdown value into CSPX.
*
* Note: it is OK if this value is zero. The WAITX instruction at the top of the
* CSP program will immediately continue if CSPX is zero when executed. However,
* if the countdown is zero, it means the transmit function was not called early
* enough for a properly timed slotted transmit. The transmit will be late.
*/
CSPX = backoffCountdown;
/*
* The receiver will be turned on during CSP execution, guaranteed.
* Since it is not possible to update C variables within the CSP,
* the new "on" state of the receiver must be set a little early
* here before the CSP is started.
*/
MAC_RX_WAS_FORCED_ON();
/* start the CSP program */
CSP_START_PROGRAM();
/*
* If the previous stored low byte of the backoff count is no longer equal to
* the current value, a rollover has occurred. This means the backoff countdown
* stored in CSPX may not be correct.
*
* In this case, the value of CSPX is reloaded to reflect the correct backoff
* countdown value (this is one less than what was just used as a rollover has
* occurred). Since it is certain a rollover *just* occurred, there is no danger
* of another rollover occurring. This means the value written to CSPX is guaranteed
* to be accurate.
*
* Also, the logic below ensures that the value written to CSPX is at least one.
* This is needed for correct operation of the WAITX instruction. As with an
* initial backoff countdown value of zero, if this case does occur, it means the
* transmit function was not called early enough for a properly timed slotted transmit.
* The transmit will be late.
*
* Finally, worth noting, writes to CSPX may not work if the CSP is executing the WAITX
* instruction and a timer rollover occurs. In this case, however, there is no possibility
* of that happening. If CSPX is updated here, a rollover has just occurred so a
* collision is not possible (still within a critical section here too).
*/
if ((lowByteOfBackoffCount != T2OF0) && (backoffCountdown > 1))
{
CSPX = backoffCountdown - 1;
}
HAL_EXIT_CRITICAL_SECTION(s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -