int8_t _bmac_rx() { int8_t n; uint8_t cnt; rf_set_rx (&bmac_rfRxInfo, g_chan); rf_polling_rx_on (); cnt=0; while ((n = rf_rx_check_fifop()) == 0) { cnt++; nrk_wait(_bmac_check_period); if(cnt>2) { #ifdef DEBUG printf( "rx timeout 1 %d\r\n",cnt ); #endif if(rx_failure_cnt<65535) rx_failure_cnt++; rf_rx_off(); return 0; } } if (n != 0) { n = 0; // Packet on its way cnt=0; while ((n = rf_polling_rx_packet ()) == 0) { cnt++; nrk_spin_wait_us(100); if (cnt > 50) { #ifdef DEBUG printf( "rx timeout 2\r\n" ); #endif rx_failure_cnt++; rf_rx_off(); return 0; } } } rf_rx_off(); if (n == 1) { // CRC and checksum passed rx_buf_empty=0; #ifdef DEBUG printf( "BMAC: SNR= %d [",bmac_rfRxInfo.rssi ); for(uint8_t i=0; i<bmac_rfRxInfo.length; i++ ) printf( "%c", bmac_rfRxInfo.pPayload[i]); printf( "]\r\n" ); #endif return 1; } else { #ifdef DEBUG printf( "CRC failed!\r\n" ); #endif rx_failure_cnt++; return 0; } rx_failure_cnt++; return 0; }
int8_t _bmac_tx() { uint8_t v,backoff, backoff_count; uint16_t b; #ifdef DEBUG nrk_kprintf( PSTR("_bmac_tx()\r\n")); #endif if(cca_active) { // Add random time here to stop nodes from synchronizing with eachother b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); //nrk_wait_ticks(b); backoff_count=1; do{ v=_bmac_channel_check(); rf_rx_off(); if(v==1) break; // Channel is busy backoff=rand()%(_b_pow(backoff_count)); #ifdef DEBUG printf( "backoff %d\r\n",backoff ); #endif // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods(backoff); backoff_count++; if(backoff_count>6) backoff_count=6; // cap it at 64 b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); // nrk_wait_ticks(b); } while(v==0); } rf_test_mode(); rf_carrier_on(); nrk_wait(_bmac_check_period); //nrk_wait_until_next_period(); rf_carrier_off(); rf_data_mode(); // send packet rf_rx_off(); pkt_got_ack=rf_tx_packet (&bmac_rfTxInfo); rf_rx_off(); tx_data_ready=0; nrk_event_signal (bmac_tx_pkt_done_signal); return NRK_OK; }
int8_t _bmac_tx() { uint8_t v,result, backoff, backoff_count; uint16_t b; if(cca_active) { // Add random time here to stop nodes from synchronizing with eachother b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); //nrk_wait_ticks(b); backoff_count=1; do { v=_bmac_channel_check(); rf_rx_off(); if(v==1) break; // Channel is busy backoff=rand()%(_b_pow(backoff_count)); // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods(backoff); backoff_count++; if(backoff_count>6) backoff_count=6; // cap it at 64 b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); // nrk_wait_ticks(b); } while(v==0); } // Give check_period worth of channel activity rf_test_mode(); rf_carrier_on(); nrk_wait(_bmac_check_period); rf_carrier_off(); rf_data_mode(); rf_rx_off(); pkt_got_ack = rf_tx_packet(&bmac_rfTxInfo); rf_rx_off(); tx_data_ready = 0; // Should signal user task here that Tx is done return NRK_OK; }
void rf_parse_rx_packet(void) { uint16_t frameControlField; uint8_t length, i; // Disable Rx while parsing packet rf_rx_off(); length = mrf_read_long(RXFIFO); //printf("\nrx_length=%d\r\n",length); if((length - RF_PACKET_OVERHEAD_SIZE - 2) <= rfSettings.pRxInfo->max_length) { // Note: 2 bytes for footer are included in Rx length rfSettings.pRxInfo->length = length - RF_PACKET_OVERHEAD_SIZE - 2; frameControlField = mrf_read_long(RXFIFO+1); frameControlField |= (mrf_read_long(RXFIFO+2) << 8); rfSettings.pRxInfo->ackRequest = !!(frameControlField & RF_FCF_ACK_BM); rfSettings.pRxInfo->seqNumber = mrf_read_long(RXFIFO+3); rfSettings.pRxInfo->srcAddr = mrf_read_long(RXFIFO+8); rfSettings.pRxInfo->srcAddr |= (mrf_read_long(RXFIFO+9) << 8); for(i = 0; i < rfSettings.pRxInfo->length; i++) { rfSettings.pRxInfo->pPayload[i] = mrf_read_long(RXFIFO+10+i); } rfSettings.pRxInfo->rssi = mrf_read_long(RXFIFO+1+length+1); rx_data_ready = 1; } // Re-enable Rx when done parsing rf_rx_on(); }
// Assuming that CCA returned 1 and a packet is on its way // Receive the packet or timeout and error int8_t _bmac_rx () { int8_t n; uint8_t cnt; rf_rx_on (); cnt = 0; //printf( "calling rx\r\n" ); dummy_t.secs = 0; dummy_t.nano_secs = 5 * NANOS_PER_MS; nrk_wait (dummy_t); n = rf_rx_packet_nonblock (); if (n != NRK_OK) { if (rx_failure_cnt < 65535) rx_failure_cnt++; rf_rx_off (); return 0; } /*while ( rf_rx_packet_nonblock() != NRK_OK ) { cnt++; nrk_wait(_bmac_check_period); if(cnt>2) { #ifdef DEBUG printf( "rx timeout 1 %d\r\n",cnt ); #endif if(rx_failure_cnt<65535) rx_failure_cnt++; rf_rx_off(); return 0; } } */ rx_buf_empty = 0; #ifdef DEBUG printf ("BMAC: SNR= %d [", bmac_rfRxInfo.rssi); for (uint8_t i = 0; i < bmac_rfRxInfo.length; i++) printf ("%c", bmac_rfRxInfo.pPayload[i]); printf ("]\r\n"); #endif rf_rx_off (); return 1; }
void bmac_nw_task () { int8_t v; int8_t e; uint8_t backoff; nrk_sig_mask_t event; while(bmac_started()==0) nrk_wait_until_next_period(); //register the signal after bmac_init has been called v=nrk_signal_register(bmac_enable_signal); if(v==NRK_ERROR) nrk_kprintf( PSTR("Failed to register signal\r\n")); backoff=0; while (1) { #ifdef NRK_SW_WDT #ifdef BMAC_SW_WDT_ID nrk_sw_wdt_update(BMAC_SW_WDT_ID); #endif #endif if(is_enabled ) { v=1; if(rx_buf_empty==1) v=_bmac_channel_check(); // If the buffer is full, signal the receiving task again. else e=nrk_event_signal (bmac_rx_pkt_signal); // bmac_channel check turns on radio, don't turn off if // data is coming. if(v==0) { if(_bmac_rx()==1) { e=nrk_event_signal (bmac_rx_pkt_signal); //if(e==NRK_ERROR) { // nrk_kprintf( PSTR("bmac rx pkt signal failed\r\n")); // printf( "errno: %u \r\n",nrk_errno_get() ); //} } //else nrk_kprintf( PSTR("Pkt failed, buf could be corrupt\r\n" )); } if(/*rx_buf_empty==1 &&*/ tx_data_ready==1) { rf_rx_off(); _bmac_tx(); } //do { nrk_wait(_bmac_check_period); // if(rx_buf_empty!=1) nrk_event_signal (bmac_rx_pkt_signal); //} while(rx_buf_empty!=1); } else { event=0; do { v=nrk_signal_register(bmac_enable_signal); event=nrk_event_wait (SIG(bmac_enable_signal)); } while((event & SIG(bmac_enable_signal))==0); } //nrk_wait_until_next_period(); } }
int8_t _bmac_channel_check() { int8_t val; rf_polling_rx_on(); nrk_spin_wait_us(250); val=CCA_IS_1; if(val) rf_rx_off(); return val; }
int8_t _bmac_channel_check() { int8_t val; rf_polling_rx_on(); nrk_spin_wait_us(250); rf_rx_check_cca(); // Run once to throw out (possibly) stale data val = rf_rx_check_cca(); if(val) rf_rx_off(); return val; }
void bmac_nw_task() { int8_t v; int8_t e; uint8_t backoff; nrk_sig_mask_t event; while(bmac_started() == 0) { nrk_wait_until_next_period(); } while(1) { if(is_enabled) { v = 1; rf_rx_on(); if(rx_buf_empty) { v = _bmac_channel_check(); } else { e = nrk_event_signal(bmac_rx_pkt_signal); // Mb // Should signal user task here as a "reminder" } if(v == 0) { // Channel detected as busy, attept to Rx _bmac_rx(); // Should signal user task here to notify of Rx } else if(tx_data_ready) { // Only try to Tx if the channel is free rf_rx_off(); // Mb _bmac_tx(); } //rf_rx_off(); // Mb nrk_wait(_bmac_check_period); } else { event =0; do { v = nrk_signal_register(bmac_enable_signal); event = nrk_event_wait(SIG(bmac_enable_signal)); } while((event & SIG(bmac_enable_signal))==0); } } }
int8_t _bmac_rx() { int8_t result; uint8_t cnt; rf_rx_on(); cnt = 0; while((result = rf_rx_check_cca()) != 0) { cnt++; nrk_wait(_bmac_check_period); if(cnt > 2) { if(rx_failure_cnt < 65535) rx_failure_cnt++; rf_rx_off(); //printf("failure1=%d\r\n",rx_failure_cnt); return 0; } } // Packet on its way cnt = 0; while((result = rf_rx_packet()) == 0) { cnt++; nrk_wait(_bmac_check_period); //nrk_spin_wait_us(100); if(cnt > 1) { if(rx_failure_cnt < 65535) rx_failure_cnt++; rf_rx_off(); //printf("failure2=%d\r\n",rx_failure_cnt); return 0; } } //printf("failure3=%d\r\n",rx_failure_cnt); rf_rx_off(); rx_buf_empty = 0; return 1; // Note: CRC is checked in hardware }
int8_t _bmac_channel_check () { int8_t val = 0; rf_rx_on (); val += rf_cca_check (); val += rf_cca_check (); val += rf_cca_check (); if (val > 1) val = 1; rf_rx_off (); return val; }
void _isa_rx (uint8_t slot) { uint8_t n; uint32_t node_mask; volatile uint8_t timeout; #ifdef LED_DEBUG nrk_led_set(1); #endif rf_set_rx (&isa_rfRxInfo, isa_param.channel); // sets rx buffer and channel rf_polling_rx_on (); // Timing for waiting for sfd timeout = _nrk_os_timer_get(); timeout+=4; // 4ms n = 0; //nrk_gpio_set(NRK_DEBUG_3); while ((n = rf_rx_check_sfd()) == 0) { if (_nrk_os_timer_get() > timeout) { //spend too much time on waiting for a pkt's arrival rf_rx_off (); #ifdef LED_DEBUG nrk_led_clr(1); #endif #ifdef RX_DEBUG printf("sfd times out.\n\r"); #endif return; } } //printf("%d\n\r",_nrk_high_speed_timer_get()); // sfd received, start receiving packet and record start time rx_start_time = _nrk_high_speed_timer_get(); // Timing for waiting for finishing packet receiving timeout = _nrk_os_timer_get(); timeout += 5; // 5ms if (n != 0) { n = 0; //printf("Packet on its way\n\r"); while ((n = rf_polling_rx_packet (false,128)) == 0) { //printf("%d\n\r",_nrk_os_timer_get()); if (_nrk_os_timer_get () > timeout) { #ifdef RX_DEBUG printf("packet is too long, times out.\n\r"); #endif // spend too much time on receiving pkt. return; // huge timeout as fail safe } } } rf_rx_off (); if (n == 1) {// successfully received packet isa_rx_data_ready = 1; //potential problem: if repeater or recipient receives noise, the DHDR would be changed. And it is highly possible that the highest bit of DHDR would be set to 0 /*if(isa_node_mode != ISA_GATEWAY) DHDR = isa_rfRxInfo.pPayload[DHDR_INDEX];*/ #ifdef RX_DEBUG printf("Repeater slot = %d, local slot is %d.\n\r", isa_rfRxInfo.pPayload[SLOT_INDEX],global_slot); #endif RX_DEBUG nrk_event_signal(isa_rx_pkt_signal); //_nrk_high_speed_timer_reset(); //nrk_high_speed_timer_wait(0,CPU_PROCESS_TIME); //nrk_gpio_set(NRK_DEBUG_3); node_mask = ((uint32_t) 1) << isa_rfRxInfo.pPayload[SRC_INDEX]; if( !(node_mask & child_list)) return; //FIXME change // ACK required if(DHDR & (1<<7)){ // Transmit ACK packet DHR = configDHR(); isa_ack_buf[DHR_INDEX]= DHR; #ifdef ACK_DEBUG //printf("DHR is %d.\n\r",DHR); #endif isa_ack_tx.pPayload = isa_ack_buf; if (DHDR & (1<<2)){ // recipient , only reply explicit ACK //isa_ack_tx.length = PKT_DATA_START-1; isa_ack_tx.length = 2; } else { //reply ACK with time offsetX offsetX = rx_start_time - slot_start_time; //printf("slot_start_time is %d,rx_start_time is %d.\n\r",slot_start_time,rx_start_time); uint8_t temp1,temp2; temp1 = (offsetX & 0xFF00)>>8; isa_ack_buf[OFFSET_HIGH]=temp1; temp2 = (offsetX & 0x00FF); isa_ack_buf[OFFSET_LOW]=temp2; #ifdef ACK_DEBUG printf("offsetX is %d\n\r", offsetX); #endif //isa_ack_tx.length = PKT_DATA_START + 1; isa_ack_tx.length = 4; } rf_tx_tdma_packet (&isa_ack_tx,slot_start_time,isa_param.tx_guard_time,&tx_start_time); }
int8_t _bmac_tx () { uint8_t v, backoff, backoff_count; uint16_t b; #ifdef DEBUG nrk_kprintf (PSTR ("_bmac_tx()\r\n")); #endif if (cca_active) { // Add random time here to stop nodes from synchronizing with eachother b = _nrk_time_to_ticks (&_bmac_check_period); b = b / ((rand () % 10) + 1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks (b); //nrk_wait_ticks(b); backoff_count = 1; do { #ifdef BMAC_MOD_CCA v=_bmac_rx(); v=!v; if (v == 1) { break; } nrk_event_signal (bmac_rx_pkt_signal); #else v = _bmac_channel_check (); if (v == 1) break; #endif // Channel is busy backoff = rand () % (_b_pow (backoff_count)); #ifdef DEBUG printf ("backoff %d\r\n", backoff); #endif // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods (backoff); backoff_count++; if (backoff_count > 6) backoff_count = 6; // cap it at 64 b = _nrk_time_to_ticks (&_bmac_check_period); b = b / ((rand () % 10) + 1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks (b); // nrk_wait_ticks(b); } while (v == 0); } // send extended preamble bmac_rfTxInfo.cca = 0; bmac_rfTxInfo.ackRequest = 0; uint16_t ms = _bmac_check_period.secs * 1000; ms += _bmac_check_period.nano_secs / 1000000; //printf( "CR ms: %u\n",ms ); //target_t.nano_secs+=20*NANOS_PER_MS; rf_rx_on (); pkt_got_ack = rf_tx_packet_repeat (&bmac_rfTxInfo, ms); // send packet // pkt_got_ack=rf_tx_packet (&bmac_rfTxInfo); rf_rx_off (); // Just in case auto-ack left radio on tx_data_ready = 0; nrk_event_signal (bmac_tx_pkt_done_signal); return NRK_OK; }