/* nrf_conf_inicial configura los registros del nrf para que funcione como PRX. 
 * En esta funcion se establece la velocidad, potencia y canal que se usaran en
 * el resto del programa */
void nrf_conf_inicial(void){
	desactivar_nrf();
	escribir_reg_8bits(0x00,0x0C); //PRIM_RX = 0
	escribir_reg_8bits(0x05,120); // Canal 120
	escribir_reg_8bits(0x06,0x07); // 1Mbps

	escribir_reg_8bits(0x02,0x03); // Habilitar recepcion en pipe0 y pipe1 [EN_RXADDR]
	escribir_reg_8bits(0x01,0x03); // Habilitar AutoAck en pipe0 y pipe1 [EN_AA]

	escribir_reg_8bits(0x03,0x03); // Direcciones de 5 bytes [SETUP_AW]
	escribir_reg_8bits(0x11,0x20); // pipe0 recibe payloads con 32 bytes
	escribir_reg_8bits(0x12,0x20); // pipe1 recibe payloads con 32 bytes

	escribir_reg_40bits(0x0A,0x65646f4e31); // pipe0 RX_ADDR

	escribir_reg_8bits(0x07,0x00); // Limpiar IRQs => REEMPLAZAR POR nrf_limpiar_flags();

	escribir_reg_8bits(0x00,0x0f); // Seleccionar PRIM_RX EN_CRC PWR_UP CRCO [CONFIG]
	
	// Delay de 5 ms (6.1.7 Timing Information [Tpd2stby] pag. 24).
	__delay_cycles(80000); // a 16MHz
    flush_rx();
	flush_tx();
	activar_nrf();

	// El nrf24l01+ queda como PRX activo.
}
예제 #2
0
파일: radio.cpp 프로젝트: vargin/scout-rf
void Radio::startListening(void) {
  write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
  write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));

  if (read_register(FEATURE) & _BV(EN_ACK_PAY)) {
    flush_tx();
  }
}
/* nrf_cargar_y_transmitir(uint8_t * data32bytes) borra cualquier paquete
 * pendiente, carga los 32 bytes del buffer data32bytes y los transmite */
void nrf_cargar_y_transmitir(uint8_t * data32bytes){
	desactivar_nrf();
	flush_tx();
	escribir_tx_payload(data32bytes);
	activar_nrf();
	__delay_cycles(2000);
	desactivar_nrf();
}
예제 #4
0
파일: radio.cpp 프로젝트: vargin/scout-rf
bool Radio::txStandBy() {
  while (!(read_register(FIFO_STATUS) & _BV(TX_EMPTY))) {
    if (get_status() & _BV(MAX_RT)) {
      write_register(STATUS, _BV(MAX_RT));
      // Non blocking, flush the data.
      flush_tx();
      return 0;
    }
  }

  return 1;
}
예제 #5
0
파일: radio.cpp 프로젝트: vargin/scout-rf
void Radio::stopListening(void) {
  if (read_register(FEATURE) & _BV(EN_ACK_PAY)) {
    _delay_us(155);
    flush_tx();
  }

  write_register(CONFIG, (read_register(CONFIG)) & ~_BV(PRIM_RX));

  // for 3 pins solution TX mode is only left with additional powerDown/powerUp cycle.
  powerDown();
  powerUp();
}
예제 #6
0
파일: radio.cpp 프로젝트: vargin/scout-rf
bool Radio::setup(void) {
  HalfDuplexSPI::setup();

  csnHigh();

  // Must allow the radio time to settle else configuration bits will not necessarily stick.
  // This is actually only required following power up but some settling time also appears to
  // be required after resets too. For full coverage, we'll always assume the worst.
  // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
  // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
  // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
  _delay_ms(5);

  // Reset CONFIG and enable 16-bit CRC.
  write_register(CONFIG, 0 | _BV(EN_CRC) | _BV(CRCO));

  // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
  // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
  // sizes must never be used. See documentation for a more complete explanation.
  setRetries(5, 15);

  uint8_t setup = read_register(RF_SETUP);

  // Then set the data rate to the slowest (and most reliable) speed supported by all
  // hardware.
  setDataRate(DataRate::RATE_1MBPS);

  write_register(FEATURE, 0);
  write_register(DYNPD, 0);

  // Reset current status
  // Notice reset and flush is the last thing we do
  write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));

  setChannel(76);

  // Flush buffers
  flush_rx();
  flush_tx();

  //Power up by default when setup() is called.
  powerUp();

  // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX
  // instead of 1500us from powerUp ) PTX should use only 22uA of power.
  write_register(CONFIG, (read_register(CONFIG)) & ~_BV(PRIM_RX));

  // If setup is 0 or ff then there was no response from module.
  return setup != 0 && setup != 0xff;
}
예제 #7
0
파일: radio.cpp 프로젝트: vargin/scout-rf
bool Radio::txStandBy(uint32_t timeout) {
  uint32_t elapsed = 0;

  while (!(read_register(FIFO_STATUS) & _BV(TX_EMPTY))) {
    if (get_status() & _BV(MAX_RT)) {
      write_register(STATUS, _BV(MAX_RT));

      if (elapsed >= timeout) {
        flush_tx();
        return 0;
      }
    }

    elapsed += 200;
    _delay_ms(200);
  }

  return 1;
}
/* Configura el nrf24l01+ como transmisor primario (PTX) en la direccion "dir" con AutoAck*/
void nrf_como_PTX(uint64_t dir){
	desactivar_nrf();
	nrf_limpiar_flags();
	escribir_reg_8bits(0x00,0x0C); // [CONFIG] como PTX y POWER-DOWN
	escribir_reg_40bits(0x0A,dir); // pipe0 RX_ADDR
	escribir_reg_40bits(0x10,dir); // TX_ADDR
	escribir_reg_8bits(0x04,0xFF); // 4ms y 15 ret.
    //__delay_cycles(10000); //CHECK THIS
    flush_rx();
	flush_tx();
    //__delay_cycles(10000);

	escribir_reg_8bits(0x00,0x0C | 0x02); // Power-Up

	// Delay de 5 ms (6.1.7 Timing Information [Tpd2stby] pag. 24).
	__delay_cycles(80000); // a 16MHz
	// Delay de 130 us (6.1.7 Timing Information [Tstby2a] pag. 24).
	__delay_cycles(3200); // a 16MHz
}
예제 #9
0
/*==================================================================================================

FUNCTION: Uart_deinit

DESCRIPTION:

==================================================================================================*/
UartResult Uart_deinit(UartHandle h)
{
   UART_CONTEXT* uart_ctxt;
   UartResult    result = UART_SUCCESS;

   UART_LOG_0(INFO,"+Uart_deinit");

   if (NULL == h)
   {
      UART_LOG_0(ERROR,"Calling Uart_deinit with a NULL handle.");
      return UART_ERROR;
   }

   uart_ctxt = (UART_CONTEXT*)h;
   if (FALSE == uart_ctxt->is_port_open)
   {
      UART_LOG_0(ERROR,"Calling Uart_deinit on a closed port.");
      return UART_ERROR;
   }

   flush_tx(uart_ctxt);

   uart_ctxt->is_port_open = FALSE;

   if(UART_SUCCESS != Uart_clock_close(uart_ctxt))
   {
      UART_LOG_0(ERROR, "Uart_clock_close failed.");
      result = UART_ERROR;
   }
   if(UART_SUCCESS != Uart_tlmm_close(uart_ctxt))
   {
      UART_LOG_0(ERROR, "Uart_tlmm_close failed.");
      result = UART_ERROR;
   }
   if(UART_SUCCESS != Uart_interrupt_close(uart_ctxt))
   {
      UART_LOG_0(ERROR, "Uart_interrupt_close failed.");
      result = UART_ERROR;
   }

   UART_LOG_0(INFO,"-Uart_deinit");
   return result;
}
예제 #10
0
// Program entry point
void main()
{
  rfcon = 0x06; // enable RF clock
  rfctl = 0x10; // enable SPI
  ien0 = 0x80;  // enable interrupts
  TICKDV = 0xFF; // set the tick divider

  // Initialise and connect the USB controller
  init_usb();

  // Flush the radio FIFOs
  flush_rx();
  flush_tx();

  // Everything is triggered via interrupts, so now we wait
  while(1)
  {
    REGXH = 0xFF;
    REGXL = 0xFF;
    REGXC = 0x08;
    delay_us(1000);
  }
}
bool NRF24L01p::transmit(void* buf, uint8_t length) {

    write_tx_payload(buf, length);

    // Pulse CE to start TX mode
    spi.set_ce_pin(1);

    // Pulse add least 10 us to start TX mode
    // Thce = 10us
    TimeUtil::delay_microseconds(11);

    // We are transmitting only one packet
    spi.set_ce_pin(0);

    TimeUtil::delay_microseconds(130);

    uint8_t status = get_status();

    while (!(status & (1 << STATUS_TX_DS | 1 << STATUS_MAX_RT))) {
        status = get_status();
    }

    reset_tx_interrupts();

    if (status & 1 << STATUS_TX_DS) {
        // Other party needs 130 us to get to RX mode again.
        // Tstby2a = 130us
        TimeUtil::delay_microseconds(130);

        return 1;
    }

    flush_tx();

    return 0;
}
예제 #12
0
파일: main.c 프로젝트: mybays/lm3s
//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);

    //
    // Initialize the OLED display and write status.
    //
    //
    // Enable the peripherals used by this example.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //PC5,PC7 EN,CSN
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE,1<<5|1<<7);

    //SPI配置
    unsigned long ulDataTx[NUM_SSI_DATA];
    unsigned long ulDataRx[NUM_SSI_DATA];
    unsigned long ulindex;
    unsigned long ultemp=0;


    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    //SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
                       SSI_MODE_MASTER, 4000000, 8);
    /*
    GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_DIR_MODE_OUT); 
    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU);  
    GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_DIR_MODE_OUT);
    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_0 , GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU);
    */
    SSIEnable(SSI0_BASE);


    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    //
    // Prompt for text to be entered.
    //
    UARTStdioInit(0);
    UARTSend((unsigned char *)"Enter text:\n\r", 12);
    UARTSend((unsigned char *)"Enter text:\n\r", 12);

    //清零接收缓冲区
    while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
    {
    }
    ulDataTx[0] = 's';
    ulDataTx[1] = 'p';
    ulDataTx[2] = 'i';

    set_nrf24l01_csn_l();
    /*
    for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
    {
    	UARTprintf("'%c' ", ulDataTx[ulindex]);
    	SSIDataPut(SSI0_BASE, ulDataTx[ulindex]);
    }
    */
    set_nrf24l01_csn_h();
    _delay_ms(1);

    if( setDataRate( RF24_250KBPS ) )
    {
        p_variant = true ;
    }

    //初始化NRF24L01
    set_module_tx();
    nrf_write_reg(NRF_CONFIG,0x0a);
    print_byte_register("CONFIG\t",NRF_CONFIG,1);

    init_NRF24L01();
    set_module_tx();

    unsigned char transfer_value[]="EEWORLD_MSP430_00";

    //set_module_tx();

    //读不出来spi数据的原因是,原来里面有没读取完的数据,需要先清理,再读写.



    setChannel(74);
    UARTprintf("getchannel:%d\r\n",getChannel());
 //   setChannel(24);
 //   UARTprintf("getchannel:%d\r\n",getChannel());

    //写地址
    nrf_write_buf(TX_ADDR,(uint8_t*)&addresses[0],5);

    uint8_t recvbuf[5];
    nrf_read_buf(TX_ADDR,&recvbuf[0],5);

    for(int i=0;i<5;i++)
    {
        UARTprintf("%d:%d ",i,recvbuf[i]);
    }
    UARTprintf("\r\n");
    //end of test write address


    uint8_t data[32];

    for(int i=0;i<32;i++)
    {
        data[i]=i;
    }


    

    UARTprintf("\r\n");
    //while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
    //{
    //}

    //重新发送前,避免写缓冲区满
    flush_tx();
    spi_write_reg(STATUS, ( spi_read_reg(STATUS) ) | _BV(MAX_RT) );
    //role=role_ping_out
    openWritingPipe(addresses[0]);
    openReadingPipe(1,addresses[1]);

    nrf_write_buf(RX_ADDR_P0,(uint8_t*)&addresses[0],5);

    unsigned char test;
    //while(1)
    {
        test=spi_read_reg(0x05);
        UARTprintf("test:%d\r\n",test);
        _delay_ms(1000);
    }

    //调试关闭
    //nrf_write_reg(EN_AA,0x00);
    nrf_write_reg(EN_RXADDR,0x02);
    //nrf_write_reg(SETUP_RETR,0x00);
    nrf_write_reg(RX_PW_P1,0x20);

    //set_module_tx();
    nrf_write_reg(NRF_CONFIG,0x0b);
    nrf_write_reg(CONFIG, nrf_read_reg(CONFIG) | _BV(PRIM_RX));
    nrf_write_reg(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
    set_nrf24l01_ce_h();
    nrf_write_buf(RX_ADDR_P0,(uint8_t*)&addresses[0],5);
    set_nrf24l01_ce_h();
    if(nrf_read_reg(FEATURE) & _BV(EN_ACK_PAY))
    {
        flush_tx();
    }

    flush_rx();

    print_status(get_status());
    nrf_write_reg(SETUP_AW,0x03);
    print_byte_register("SETUP_AW\t",SETUP_AW,1);
    print_address_register("RX_ADDR_P0-1",RX_ADDR_P0,2);
    print_byte_register("RX_ADDR_P2-5",RX_ADDR_P2,4);

    print_address_register("TX_ADDR\t",TX_ADDR,1);

    print_byte_register("RX_PW_P0-6",RX_PW_P0,6);


    print_byte_register("EN_AA\t",EN_AA,1);
    print_byte_register("EN_RXADDR",EN_RXADDR,1);
    print_byte_register("RF_CH\t",RF_CH,1);
    print_byte_register("RF_SETUP",RF_SETUP,1);

    print_byte_register("CONFIG\t",NRF_CONFIG,1);
    print_byte_register("DYNPD/FEATURE",DYNPD,2);


    UARTprintf("Data Rate\t = %s\r\n", pgm_read_word(&rf24_datarate_e_str_P[getDataRate()]));
    UARTprintf("Model\t\t = %s\r\n",   pgm_read_word(&rf24_model_e_str_P[isPVariant()]));
    UARTprintf("CRC Length\t = %s\r\n",pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()]));
    UARTprintf("PA Power\t = %s\r\n",  pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()]));

    Init_Timer_A();

    set_nrf24l01_ce_h();
    //将业务数据写入:WR_TX_PLOAD

    uint8_t fifo_status,status,state,i;
    while(1)
    {
        fifo_status=spi_read_reg(FIFO_STATUS);
        if(fifo_status&0x02)
        {
            status=spi_read_reg(STATUS);
            if(status&_BV(RX_DR))
            {
                state=spi_send_byte(RD_RX_PLOAD);
                for(i=0;i<RX_PLOAD_WIDTH;i++)
                {
                    status=spi_send_byte(0xff);
                    //buf[i]=status;
                }
                nrf_write_reg(FLUSH_RX,0xFF);
                //UARTprintf(".");
                counter++;
            }
            if(status &0x02)
            {
                nrf_write_reg(FLUSH_RX,0xFF);
                //UARTprintf(".");
                counter++;
            }

            nrf_rx_packet(data);
        }
    }

    while(available(0))
    {
        //UARTprintf(".");
        if(nrf_rx_packet(data) == 0)
        {
            counter++;
        }
        
        //UARTprintf(".");
        //_delay_ms(50);
        /*
        set_nrf24l01_ce_l();
        nrf_write_buf(WR_TX_PLOAD,data,TX_PLOAD_WIDTH);
        set_nrf24l01_ce_h();
        _delay_ms(30);
        */
    }
}
예제 #13
0
int main(){
    uint8_t txretry_count=0, txretry_latch=0;

    WDTCTL = (WDTPW + WDTHOLD);
    DCOCTL = CALDCO_16MHZ;
    BCSCTL1 = CALBC1_16MHZ;
    BCSCTL2 = DIVS_1;  // SMCLK = 8MHz

    // Inicializacao do transceiver
    rf_crc = RF24_EN_CRC;
    rf_addr_width = 5;
    rf_speed_power = RF24_SPEED_MIN | RF24_POWER_MAX;
    rf_channel = 8;
    msprf24_init();
    msprf24_open_pipe(0, 1);  // This is only for receiving auto-ACK packets.
    msprf24_set_pipe_packetsize(0, 0);  // Dynamic payload support
        // Note: Pipe#0 is hardcoded in the transceiver hardware as the designated "pipe" for a TX node to receive
        // auto-ACKs.  This does not have to match the pipe# used on the RX side.

    Serial_config();

    // Main loop
    while (1) {
        // Handle any nRF24 IRQs first
        if (rf_irq & RF24_IRQ_FLAGGED) {
            msprf24_get_irq_reason();

            if (rf_irq & RF24_IRQ_TX) {
                msprf24_irq_clear(RF24_IRQ_TX);
                flush_tx();
                w_rx_addr(0, (uint8_t*)masterAddr);
                msprf24_powerdown();
            }

            if (rf_irq & RF24_IRQ_TXFAILED) {
                msprf24_irq_clear(RF24_IRQ_TXFAILED);
                if (txretry_count) {
                    txretry_count--;
                    if (!txretry_latch) {
                        txretry_latch = 1;
                        tx_reuse_lastpayload();
                    }
                    pulse_ce();
                } else {
                    // Ran out of retries, give up
                    flush_tx();
                    w_rx_addr(0, (uint8_t*)masterAddr);
                    txretry_latch = 0;
                    msprf24_powerdown();
                }
            }
            // No need to handle RX packets since we never enter RX mode
        }

        if (handle_serial){
            if(serial_data_rcv == START_CHAR){
                pl_index == 0;
            }
            else if(serial_data_rcv == END_CHAR){
                send_pkg = true;
                pl_index == 0;
            }
            else if(pl_index < PL_SIZE){
                rfpayload[pl_index++] = serial_data_rcv;
            }
            else{
                pl_index = 0;
            }

            handle_serial = false;
        }

        if (msprf24_queue_state() & RF24_QUEUE_TXEMPTY && send_pkg) {

            Serial_escreve_texto("\nEnviando pacote: ");
            Serial_escreve_texto(rfpayload);

            msprf24_standby();
            w_tx_addr((uint8_t*)nodeAddr);
            w_rx_addr(0, (uint8_t*)nodeAddr);  // To catch the auto-ACK reply
            w_tx_payload(2, (uint8_t*)rfpayload);
            msprf24_activate_tx();
            txretry_count = 20;  // Try damned hard to send this, retrying up to 20 * ARC times (ARC=15 by default)

            send_pkg = false;
        }

    }
}
예제 #14
0
파일: main.c 프로젝트: elpapais/nrfdmx
int main()
{
	uint8_t rfbuf[32], i, do_lpm, pktlen, pipeid;

	WDTCTL = WDTPW | WDTHOLD;


	// I/O ports used for status LED
	//P3DIR |= BIT6;
	P1DIR |= BIT0;
	//P1OUT &= ~BIT7;
	P1OUT &= ~BIT0;
	//P3OUT |= BIT6;  // Blue LED signifies clock startup

	/* MSP430 F5172 */
	//ucs_clockinit(16000000, 0, 0);
	/* MSP430 G-series */
	DCOCTL = CALDCO_16MHZ;
	BCSCTL1 = CALBC1_16MHZ;
	BCSCTL2 = DIVS_1;

	//P3OUT &= ~BIT6;



	// Configure Nordic nRF24L01+
	rf_crc = RF24_EN_CRC | RF24_CRCO; // CRC enabled, 16-bit
	rf_addr_width      = 5;
	rf_speed_power     = RF_SPEED | RF24_POWER_MAX;  // RF_SPEED from tcsender.h
	rf_channel         = RF_CHANNEL;  // This #define is located in tcsender.h
	msprf24_init();
	msprf24_open_pipe(0, 0);
	msprf24_set_pipe_packetsize(0, 0);

	packet_init_tasklist();
	dmx512_init();

	// Submit one color change.
	memcpy(dmx512_buffer, rgb_cust, 3);
	dmx512_output_channels(0x00, 1, dmx512_buffer, 3);

	while(1) {
		do_lpm = 1;

		// Handle RF acknowledgements
		if (rf_irq & RF24_IRQ_FLAGGED || msprf24_rx_pending()) {
			msprf24_get_irq_reason();

			// Handle TX acknowledgements
			if (rf_irq & RF24_IRQ_TX) {
				// Acknowledge
				msprf24_irq_clear(RF24_IRQ_TX);
				P1OUT &= ~BIT0;
			}

			if (rf_irq & RF24_IRQ_TXFAILED) {
				msprf24_irq_clear(RF24_IRQ_TXFAILED);
				flush_tx();
			}

			if (rf_irq & RF24_IRQ_RX || msprf24_rx_pending()) {
				pktlen = r_rx_peek_payload_size();
				if (pktlen > 0 && pktlen < 33) {
					pipeid = r_rx_payload(pktlen, (char*)rfbuf);
					if (pipeid == 1) {
						for (i=0; i < pktlen; i++) {
							if (rfbuf[i]) {
								/* Process this packet if it's valid (and payload length doesn't send us
								 *   past the end of the rfbuf buffer)
								 */
								if ( (i+rfbuf[i+1] + 1) < pktlen ) {
									packet_processor(rfbuf[i],
											 rfbuf[i+1],
											 &rfbuf[i+2]);
									i += rfbuf[i+1] + 1;
								} else {
									i = pktlen;  /* Otherwise, we're done, we assume the
										      *   the rest of the payload is corrupt.
										      */
								}
							} /* rfbuf[i] != 0x00 (i.e. valid program ID) */
						} /* for(0 .. pktlen) */
					} /* pipeid == 1 */
				} else {
					// False alarm; bad packet, nuke it.
					flush_rx();
				} /* pktlen is 1..32 */
				msprf24_irq_clear(RF24_IRQ_RX);
			} /* rf_irq & RF24_IRQ_RX */

			do_lpm = 0;
		}  /* rf_irq & RF24_IRQ_FLAGGED */

		if (packet_task_next() != NULL) {
			packet_process_txqueue();
		}

		if (do_lpm)
			LPM4;
	} /* while(1) */

	return 0;  // Should never reach here
}