| 295 | ---- |
| 296 | |
| 297 | The biggest addition we need to make to the DCF is to create a function that polls the TSF timer and tunes to the scheduled channel when needed. The absolute TSF timer value is mapped onto an index into the hopping sequence defined in the global variable {{{hop_vec}}}. If the index has changed since the last iteration, the radio is immediately re-tuned to the new center frequency. The mapping of timer values to hopping sequence indexes is arbitrary as long as the mapping is the same on every node. This implementation uses a simple quantization function to implement the mapping. |
| 298 | |
| 299 | Furthermore, this function should look out for a subtle race condition that might occur if a packet has been submitted to the [wiki:802.11/MAC/Support_HW MAC Support Core] prior to the execution of this function. If a transmission is currently underway, this function should ''not'' change to a new frequency even if the schedule indicates otherwise. After the transmission is complete, it is safe to tune to the new channel. |
| 300 | |
| 301 | Finally, we'll provide a return value with this function that indicates whether or not it is safe to submit new transmissions to the MAC Support Core. With this feature, we can enforce an arbitrarily long guard interval just prior to a scheduled channel hop boundary to account for any jitter caused by imperfect synchronization at various nodes in the network. Add the following function to the DCF code: |
| 302 | |
| 303 | {{{ |
| 304 | #!c |
| 305 | |
| 306 | //TS_USEC_SHIFT of 12 will increment our hop index every 4096 usec. |
| 307 | #define TS_USEC_SHIFT 12 |
| 308 | |
| 309 | inline int poll_hop(){ |
| 310 | u64 curr_timestamp; |
| 311 | static u8 curr_channel = 0; |
| 312 | u8 next_channel; |
| 313 | u32 curr_hop_num = 0; |
| 314 | u32 mac_hw_status; |
| 315 | |
| 316 | curr_timestamp = 0; |
| 317 | if(enable_hop){ |
| 318 | curr_timestamp = get_usec_timestamp(); |
| 319 | curr_hop_num = curr_timestamp>>TS_USEC_SHIFT; |
| 320 | next_channel = hop_vec[((curr_hop_num)%HOP_SEQ_LEN)]; |
| 321 | |
| 322 | if(next_channel != curr_channel){ |
| 323 | |
| 324 | //Update DIFS to be safe |
| 325 | //This will help ensure that any currently-pending transmissions don't start while we are changing channels |
| 326 | wlan_mac_set_DIFS((T_DIFS+255)*10); |
| 327 | wlan_mac_set_TxDIFS(((T_DIFS+255)*10) - (TX_PHY_DLY_100NSEC)); |
| 328 | |
| 329 | //Even with the above DIFS tweak, there is still a race condition if a transmission just started. To handle this |
| 330 | //race, we will explicitly check to see if the PHY is running and quit this function if so. |
| 331 | //We should make sure the Tx PHY isn't currently running. |
| 332 | mac_hw_status = wlan_mac_get_status(); |
| 333 | |
| 334 | if((mac_hw_status & WLAN_MAC_STATUS_MASK_TX_A_PENDING) && (mac_hw_status & WLAN_MAC_STATUS_MASK_TX_PHY_ACTIVE)){ |
| 335 | //Ongoing transmission. Don't change channels |
| 336 | |
| 337 | //Reset DIFS |
| 338 | wlan_mac_set_DIFS((T_DIFS)*10); |
| 339 | wlan_mac_set_TxDIFS(((T_DIFS)*10) - (TX_PHY_DLY_100NSEC)); |
| 340 | |
| 341 | return -1; |
| 342 | } |
| 343 | |
| 344 | curr_channel = next_channel; |
| 345 | |
| 346 | //Raise the debug GPIO so we can see how long this takes |
| 347 | //We will probe these pins on an oscilloscope |
| 348 | REG_SET_BITS(WLAN_RX_DEBUG_GPIO, 0xFF); |
| 349 | |
| 350 | //Tune to the new frequency |
| 351 | radio_controller_setCenterFrequency(RC_BASEADDR, (RC_ALL_RF), RC_24GHZ, wlan_mac_low_wlan_chan_to_rc_chan(next_channel)); |
| 352 | wlan_mac_reset_NAV_counter(); |
| 353 | |
| 354 | //Reset DIFS |
| 355 | wlan_mac_set_DIFS((T_DIFS)*10); |
| 356 | wlan_mac_set_TxDIFS(((T_DIFS)*10) - (TX_PHY_DLY_100NSEC)); |
| 357 | |
| 358 | //Lower the debug GPIO |
| 359 | REG_CLEAR_BITS(WLAN_RX_DEBUG_GPIO, 0xFF); |
| 360 | |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | |
| 365 | //Poll IPC rx |
| 366 | //Here, we slice of the bottom 12 bits of the usec counter. If that value is |
| 367 | //less that 4000 usec out of the 4096 usec hop dwell time, we'll return |
| 368 | //a value of 0 to let the calling function know it is safe to start a new |
| 369 | //transmission. If we are in the window of 96 usec at the end of the dwell, |
| 370 | //we'll return a value of -1 to let the calling function know that it isn't safe |
| 371 | //to start any new transmissions |
| 372 | if((curr_timestamp & 0xFFF) < 4000){ |
| 373 | //If we are currently outside of the guard interval at the end of a hop |
| 374 | return 0; |
| 375 | } else { |
| 376 | //If we are currently inside of the guard interval at the end of a hop |
| 377 | return -1; |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | }}} |
| 382 | |