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(); }
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_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; }
// This function will put the node into a low-duty checking mode to save power void tdma_snooze() { int8_t v; uint8_t i; // stop the software watchdog timer so it doesn't interrupt nrk_sw_wdt_stop(0); // This flag is cleared only by the button interrupt snoozing=1; // Setup the button interrupt nrk_ext_int_configure( NRK_EXT_INT_1,NRK_LEVEL_TRIGGER, &wakeup_func); // Clear it so it doesn't fire instantly EIFR=0xff; nrk_ext_int_enable( NRK_EXT_INT_1); // Now loop and periodically check for packets while(1) { nrk_led_clr(RED_LED); nrk_led_clr(GREEN_LED); rf_power_up(); rf_rx_on (); // check return from button interrupt on next cycle if(snoozing==0 ) return; tmp_time.secs=0; tmp_time.nano_secs=10*NANOS_PER_MS; nrk_led_set(RED_LED); // Leave radio on for two loops of 10ms for a total of 20ms every 10 seconds for(i=0; i<2; i++ ) { v = _tdma_rx (); if(v==NRK_OK) { nrk_led_set(RED_LED); nrk_ext_int_disable( NRK_EXT_INT_1); nrk_sw_wdt_update(0); nrk_sw_wdt_start(0); return NRK_OK; } nrk_wait(tmp_time); } nrk_led_clr(RED_LED); rf_power_down(); tmp_time.secs=10; tmp_time.nano_secs=0; nrk_sw_wdt_stop(0); nrk_wait(tmp_time); } }
// 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; }
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 }
void Task1 () { uint16_t cnt; uint8_t len,i; //printf ("My node's address is %d\r\n", NODE_ADDR); //printf ("Task1 PID=%d\r\n", nrk_get_pid ()); rfRxInfo.pPayload = rx_buf; rfRxInfo.max_length = RF_MAX_PAYLOAD_SIZE; nrk_int_enable(); rf_init (&rfRxInfo, 13, 0x2420, 0x1214); cnt = 0; slip_init (stdin, stdout, 0, 0); rf_rx_on(); while (1) { while (rf_rx_packet_nonblock () != NRK_OK) { nrk_wait_until_next_period(); } rx_packet_len = rfRxInfo.length; for(i=0; i<rfRxInfo.length; i++ ) slip_tx_buf[i]=rfRxInfo.pPayload[i]; slip_tx_buf[10] = rfRxInfo.rssi; while(uart_tx_busy==1) nrk_wait_until_next_period(); uart_tx_busy=1; slip_tx (slip_tx_buf, rx_packet_len); uart_tx_busy=0; } }
uint8_t rf_tx_packet(RF_TX_INFO *pRTI) { uint16_t frameControlField; uint8_t packetLength; uint8_t success, i; // Note: checksum is automatic in HW LPC_GPIO1->FIOPIN ^= 1<<31; packetLength = pRTI->length + RF_PACKET_OVERHEAD_SIZE; frameControlField = RF_FCF_NOACK; if(auto_ack_enable || pRTI->ackRequest) frameControlField |= RF_ACK_BM; if(security_enable) frameControlField |= 0x0000; // TODO: Paul Gurniak, add security mrf_write_long(TXNFIFO, RF_PACKET_OVERHEAD_SIZE); // No checksum, overhead is all header mrf_write_long(TXNFIFO+1, packetLength); // Write header bytes mrf_write_long(TXNFIFO+2, frameControlField & 0xFF); mrf_write_long(TXNFIFO+3, frameControlField >> 8); mrf_write_long(TXNFIFO+4, rfSettings.txSeqNumber); mrf_write_long(TXNFIFO+5, rfSettings.panId & 0xFF); mrf_write_long(TXNFIFO+6, rfSettings.panId >> 8); mrf_write_long(TXNFIFO+7, pRTI->destAddr & 0xFF); mrf_write_long(TXNFIFO+8, pRTI->destAddr >> 8); mrf_write_long(TXNFIFO+9, rfSettings.myAddr & 0xFF); mrf_write_long(TXNFIFO+10, rfSettings.myAddr >> 8); // Write payload for(i = 0; i < pRTI->length; i++) { mrf_write_long(TXNFIFO+11+i, pRTI->pPayload[i]); // pPayload is the user defined part of data packet right ? } if(pRTI->cca) { uint8_t cnt = 0; if(!rfSettings.receiveOn) { rf_rx_on(); } while(!rf_rx_check_cca()) { cnt++; if(cnt > 100) { return FALSE; } halWait(100); } } tx_status_ready = 0; mrf_write_short(TXNCON, auto_ack_enable ? 0x05 : 0x01); // Send contents of TXNFIFO as packet //putchar(auto_ack_enable); // Wait for Tx to finish while(!tx_status_ready); wait_ms(50); success = 1; //putchar(auto_ack_enable); if(auto_ack_enable || pRTI->ackRequest) { uint8_t k = mrf_read_short(TXSTAT); success = !(k & 0x01); //printf("ACK%c",k); } //printf("tx_pkt success = %d\r\n",success); // Transmission works fine : Checked by Madhur, success = 1only when the receiver is enabled // Increment sequence, return result rfSettings.txSeqNumber++; return success; }
void tdma_nw_task () { int8_t v, i; uint16_t slot, tmp,sync; nrk_sig_mask_t event; do { nrk_wait_until_next_period (); } while (!tdma_started ()); _tdma_slot_time.nano_secs = TDMA_DEFAULT_SLOT_MS * NANOS_PER_MS; _tdma_slot_time.secs = 0; //register the signal after bmac_init has been called v = nrk_signal_register (tdma_enable_signal); if (v == NRK_ERROR) nrk_kprintf (PSTR ("Failed to register signal\r\n")); slot = 0; //rf_set_rx (&tdma_rfRxInfo, tdma_chan); while (1) { if (tdma_mode == TDMA_HOST) { sync_status=1; // HOST is always synced // This is the downstream transmit slot if (slot == 0) { //rf_rx_off(); // If there is no pending packet, lets make an empty one if (tx_data_ready == 0) { tdma_rfTxInfo.pPayload = tdma_tx_buf; // Setup the header data tdma_rfTxInfo.pPayload[TDMA_DST_LOW] = 0xff; // dst tdma_rfTxInfo.pPayload[TDMA_DST_HIGH] = 0xff; tdma_rfTxInfo.pPayload[TDMA_SRC_LOW] = 0x00; // src tdma_rfTxInfo.pPayload[TDMA_SRC_HIGH] = 0x00; tdma_rfTxInfo.pPayload[TDMA_SEQ_NUM_LOW] = 0x00; // seq num tdma_rfTxInfo.pPayload[TDMA_SEQ_NUM_HIGH] = 0x00; tdma_rfTxInfo.length = TDMA_PCF_HEADER; } tdma_rfTxInfo.pPayload[TDMA_CYCLE_SIZE_LOW] = tdma_slots_per_cycle & 0xff; // cycle size tdma_rfTxInfo.pPayload[TDMA_CYCLE_SIZE_HIGH] = tdma_slots_per_cycle >> 8; tdma_rfTxInfo.pPayload[TDMA_SLOT_LOW] = 0; // slot tdma_rfTxInfo.pPayload[TDMA_SLOT_HIGH] = 0; tdma_rfTxInfo.pPayload[TDMA_SLOT_SIZE] = tdma_slot_len_ms; nrk_time_get (&_tdma_next_wakeup); tdma_rfTxInfo.destAddr = 0xffff; tdma_rfTxInfo.ackRequest = 0; tdma_rfTxInfo.cca = 0; _tdma_tx (); rf_rx_on (); } else { // Upstream data slot v = _tdma_rx (); if (v == 1) tdma_last_tx_slot = slot; } slot++; if (slot >= tdma_slots_per_cycle + 1) slot = 0; nrk_time_add (&_tdma_next_wakeup, _tdma_next_wakeup, _tdma_slot_time); nrk_time_compact_nanos (&_tdma_next_wakeup); nrk_wait_until (_tdma_next_wakeup); }
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; }