Пример #1
0
// Target function to timer, sends ping packet after a delay
// note that arguments are via static vars due to the indirect nature of the call
static void
macDoPingRequest(void)
{
    ftPing frame;

    frame.fcf = FCF_DATA;
    frame.seq = macConfig.dsn++;
    frame.panid = macConfig.panId;
    frame.srcAddr = macConfig.shortAddress;
    frame.originAddr = macConfig.shortAddress;
    frame.finalDestAddr = pingAddr;
    frame.rssi = radioGetSavedRssiValue();
    frame.lqi = radioGetSavedLqiValue();
    frame.type = pingType;

    // Set high bit of type if we're sleeping
    if (macConfig.sleeping && NODE_TYPE == ENDDEVICE && NODE_SLEEP)
       	frame.type |= 0x80;

#if (NODE_TYPE == COORD)
    {
#if DEBUG==2
 debugMsgStr("\r\nin macDoPingRequest");
#endif
    	// Find the top parentpin
        u8 addr = macGetTopParent(pingAddr);
        frame.destAddr = addr;
        // See if the child is sleeping (only the coord sends directly to a child node)
        if (NODE_SLEEP &&
            macIsChild(addr)&&
            macIsChildSleeping(addr))
        {
            // Send it later, after child is awake
#if DEBUG==2
debugMsgStr("\r\ncalling macHoldFrame for ping response");
#endif
            macHoldFrame(addr, (u8*)&frame, sizeof(ftPing));
            // Don't send frame right now
            return;
        }
        else
        {
#if DEBUG==2
debugMsgStr("\r\n child: ");
debugMsgInt(addr);
debugMsgStr(" not sleeping");
#endif
        }

    }
#else
        // End/router nodes
        frame.destAddr = macConfig.parentShortAddress;
#endif
#if DEBUG==2
debugMsgStr(" sending Ping Response now\n\r");
#endif

    radioSendData(sizeof(ftPing), (u8*)&frame);
}
Пример #2
0
void
macData_BC_Request( u8 len, u8 * data)
{
    ftData *data_frame = (ftData*)(mac_buffer_tx+1); // Create a struct pointer to the global variable...

    // if we have not found a channel to broadcast on do nothing
    if (panDescriptor.logicalChannel  == 0xff)
    	return;

    Led1_on();
    debugMsgStr("\r\nmacData_BC_Request->");

    // Build the frame.
    data_frame->fcf=FCF_DATA_NOACK; //FCF Data frame no ACK -- to prevent multiple acks
    data_frame->seq = macConfig.dsn++;
    data_frame->panid = macConfig.panId;
    data_frame->srcAddr = macConfig.shortAddress;
    data_frame->originAddr = macConfig.shortAddress;
    data_frame->finalDestAddr = BROADCASTADDR;
    data_frame->destAddr = BROADCASTADDR;
    data_frame->type =DATA_FRAME;

    u8 i;
    for(i=0; i<len; i++)
        ((u8*)&data_frame->payload)[i] = *data++;

    *mac_buffer_tx = len + ftDataHeaderSize; // save length away

     macConfig.busy = true;  // this locks out debug tasks
     radioSendData(*mac_buffer_tx, (u8*)data_frame);
     Led1_off();
}
Пример #3
0
/**
   Send a ping packet (either request or response) to another node.

   param:  pingTypeArg Which type of ping to send, either  PING_REQ_FRAME or   PING_RSP_FRAME.

   param:  addr Short address of node to send ping
*/
void
macPing(u8 pingTypeArg, u16 addr)
{
    if (addr == macConfig.shortAddress)
        // Don't send to self
        return;

    if (!macConfig.associated)
        // Broadcast addr
        return;

    pingAddr = addr;
    pingType = pingTypeArg;

debugMsgStr("\r\nmacPing to: ");
debugMsgInt(pingAddr);
debugMsgStr(" type: ");
debugMsgInt(pingType); // 2 == request 3== response
debugMsgStr("\r\n");

#   if (NODE_TYPE == COORD)
    {

        u8 rpSent;
        rpSent = macSendRoutingPacket(addr); 						// First send a routing packet
#if DEBUG==2
debugMsgStr("\r\nsetting up Alarm for ping response");
#endif
        macSetAlarm(rpSent ? MAC_RP_DELAY : 0, macDoPingRequest);	// Then send the Ping (response)
        macConfig.busy = true;
    }
#   else
    {

        // End/router nodes
    	macDoPingRequest();
        macConfig.busy = true;
    }
#   endif
}
Пример #4
0
/**
   Save a frame for transmission later.  Used to store frames for
   sleeping children.

   param:  addr Short address of recipient node

   param:  len Length of the frame to store

   param:  buf Pointer to buffer containing the frame to save
*/
void
macHoldFrame(u16 addr, u8 *buf, u8 len)
{
#   if ((NODE_TYPE == ROUTER || NODE_TYPE == COORD) && NODE_SLEEP )
    {
        u8 i,done=0;

        for (i=0;i<STORED_FRAMES;i++)
        {
            if (!storedFrames[i].len)
            {
                if (!done)  // Only store once
                {
#if DEBUG
debugMsgStr("\r\nHolding frame for sleeping child");
#endif
					// This one's free, use it
                    storedFrames[i].len = len;
                    storedFrames[i].addr = addr;
                    memcpy(storedFrames[i].buf, buf, len);
                    // Don't store this frame twice
                    done = 1;
                }
            }
            else
            {
                // This item is used, make sure it isn't for this address,
                // since we only want to store one pending frame for each
                // sleeping node.
                if (storedFrames[i].addr == addr)
                    // Delete this frame
                    storedFrames[i].len = 0;
            }
        }
    }
# endif
}
Пример #5
0
/**
   Save a frame for transmission later. Used to store frames for
   sleeping children.

   @param addr Short address of recipient node

   @param pFrame Pointer to buffer containing the frame and length information
 */
void macHoldFrame(u16 addr, u8 *pFrame)
{
   if (NODETYPE != ENDDEVICE && RUMSLEEP && VLP)
   {
      u8 i,done=0;

      for (i=0;i<STORED_FRAMES;i++)
      {
         if (!storedFrames[i].len)
         {
            if (!done)  // Only store once
            {
               debugMsgStr("\r\nHolding frame");
               // This one's free, use it
               storedFrames[i].len = ((rx_frame_t*)pFrame)->length;
               storedFrames[i].addr = addr;
               //memcpy(storedFrames[i].buf, buf, len);
               memcpy(storedFrames[i].buf, ((rx_frame_t*)pFrame)->data, ((rx_frame_t*)pFrame)->length);
               // Don't store this frame twice
               done = 1;
            }
         }
         else
         {
            // This item is used, make sure it isn't for this address,
            // since we only want to store one pending frame for each
            // sleeping node.
            if (storedFrames[i].addr == addr)
               // Delete this frame
               storedFrames[i].len = 0;
         }
      }
   }

   bmm_buffer_free(pFrame); // free buffer
}
Пример #6
0
/**
   Send a frame that has been stored for a child node.  This is meant
   to be called immediately upon receiving a packet from a sleeping child node.
*/
void macSendStoredFrame(u16 addr)
{
#   if ((NODE_TYPE == ROUTER || NODE_TYPE == COORD) && NODE_SLEEP )
    {
        u8 i;

        // See if a frame is stored for this node
        for (i=0;i<STORED_FRAMES;i++)
        {
            if (storedFrames[i].len &&
                storedFrames[i].addr == addr)
            {
#if DEBUG
debugMsgStr("\r\nMac sending postponed frame \r\n");
#endif
                // Send this frame, remove checksum
                radioSendData(storedFrames[i].len, storedFrames[i].buf);
                // Clear out this frame
                storedFrames[i].len = 0;
            }
        }
    }
#   endif
}
Пример #7
0
/**
   This function is called when the MAC receives a packet that is
   addressed to this node.  The packet is dispatched according to its
   contents.
 */
void macDataIndication(uint8_t* pFrame)
{

   // Sort out the different types of data packets.
   ftData *frame = (ftData*)(((rx_frame_t*)pFrame)->data);

   /*
#if (__arm__)
    volatile s16 queue;
    if(fnGetTCP_state(host_socket) == TCP_STATE_ESTABLISHED)
    {
        if( (frame->fcf != FCF_BEACONREQ) &&
            (frame->fcf != FCF_ASSOC_REQ_DIRECT) &&
            (frame->fcf != FCF_ASSOC_REQ_IND) )
        {
            // ACK handling should occur in the tcpListener function in
            // rumtask.c.
            // fnSendBufTCP returns the number of bytes buffered if successful...
            queue = fnSendBufTCP(host_socket, (u8 *)"WIRELESSD", 9, TCP_BUF_SEND);
            if(telPrintReading && (queue > 0))
                fnDebugMsg("\r\nWIRELESSD buffered for TCP");
            else
                fnDebugMsg("\r\nWIRELESSD buffer problem");
            queue = fnSendBufTCP(host_socket, mac_buffer_rx, mac_buffer_rx[0]+1, TCP_BUF_SEND);
            if(telPrintReading && (queue > 0))
                fnDebugMsg("\r\nData indication buffered for TCP");
            else
                fnDebugMsg("\r\nData indication buffer problem");
        }
    }
#endif
    */
   switch (frame->type & 0x7f)  // Mask high bit just in case it was somehow missed
   {
   case DATA_FRAME:
      // Plain old data, send it up the chain
      appDataIndication();
      break;
   case DEBUG_FRAME:
      // Frame containing debug message, print it on coord
      if (NODETYPE == COORD && OTA_DEBUG && DEBUG)
      {
         debugMsgStr("\r\nNode ");
         debugMsgInt(frame->originAddr);
         debugMsgStr(": ");

         // Remove leading cr/lf's from string
         u8 *p = frame->payload;
         while (*p)
         {
            if (*p > ' ')
               break;
            p++;
         }
         debugMsgStr((char *)p);
      }
      break;
   case WAKE_NODE:
      // Wake up the end node.
      if (NODETYPE == ROUTER)
      {
         u8 addr = ((ftWake*)frame)->addr;
         // See if this is from parent or child
         if ((((ftWake*)frame)->srcAddr) == macConfig.parentShortAddress)
            // Set the flag to wake up the end node when it sends a packet
            macWakeChildNode(addr);
      }
      if (NODETYPE == ENDDEVICE)
      {
         // Wake yourself up now
         macConfig.sleeping = false;
         // Send parent a confirmation that we are awake
         macDataRequestInt(macConfig.parentShortAddress,
               2,
               (u8*)&macConfig.shortAddress,
               WAKE_NODE);
         debugMsgStr("\r\nAwake");
      }
      break;
   case PING_REQ_FRAME:
      // We got a ping request, let the app handle that
      appPingReq(frame->originAddr);
      break;
   case PING_RSP_FRAME:
      // We got a ping response, app will handle it
      appPingRsp(frame->originAddr);
      break;
   case DROP_CHILD_FRAME:
      // Coordinator is telling us to drop a child
      if (NODETYPE == ROUTER)
         macRemoveChild(*(u16*)(&frame->payload));
      break;
   case DATA_FRAME_6LOWPAN:
      //6lowpan data indication
      if (IPV6LOWPAN == 1)
         //sixlowpan_DataIndication(frame, *mac_buffer_rx - 16);
         sixlowpan_DataIndication(frame, (((rx_frame_t*)pFrame)->length) - 16);
      break;
   default:
      break;
   }
}
Пример #8
0
/**
   This function is called when the MAC receives a packet that is
   addressed to this node.  The packet is dispatched according to its
   contents.
*/
void
macDataIndication(u16 dest)
{
    // Sort out the different types of data packets.
   ftData *frame = (ftData*)(mac_buffer_rx+1);
   u8 pl_len = *mac_buffer_rx - 16;
#if DEBUG==2
    debugMsgStr("\r\nmacDataIndication<-");
#endif
    switch (frame->type & 0x7f)  // Mask high bit just in case it was somehow missed
    {
		case DATA_FRAME:
			// Data, send it up the chain
			appDataIndication(frame->payload, pl_len, (dest ==  BROADCASTADDR));
			break;

		case DEBUG_FRAME:
			// Frame containing debug message, print it on coord
			if (NODE_TYPE == COORD && OTA_DEBUG && DEBUG)
			{
				debugMsgStr("\r\nNode ");
				debugMsgInt(frame->originAddr);
				debugMsgStr(": ");

				// Remove leading cr/lf's from string
				u8 *p = frame->payload;
				while (*p)
				{
					if (*p > ' ')
						break;
					p++;
				}
				debugMsgStr_d((char *)p);
			}
			break;

		case WAKE_NODE:
			// Wake up the end node.
#if (NODE_TYPE == ROUTER)
			{
				u8 addr = ((ftWake*)frame)->addr;
				// See if this is from parent or child
				if ((((ftWake*)frame)->srcAddr) == macConfig.parentShortAddress)
					// Set the flag to wake up the end node when it sends a packet
					macWakeChildNode(addr);
			}
#endif

#if (NODE_TYPE == ENDDEVICE) /* also include BC_ENDDEVICE ?*/
			{
				// Wake yourself up now
				macConfig.sleeping = false;
				// Send parent a confirmation that we are awake
				macDataRequestInt(macConfig.parentShortAddress,2,
								  (u8*)&macConfig.shortAddress,WAKE_NODE);
				debugMsgStr("\r\nAwake");
			}
#endif
			break;

		case PING_REQ_FRAME:
			// We got a ping request, let the app handle that
			appPingReq((ftPing *) (mac_buffer_rx+1));
			break;

		case PING_RSP_FRAME:
			// We got a ping response, app will handle it
			appPingRsp((ftPing *) (mac_buffer_rx+1));
			break;

#if (NODE_TYPE == ROUTER)
		case DROP_CHILD_FRAME:
			// Coordinator is telling us to drop a child
			macRemoveChild(*(u16*)(&frame->payload));
			break;
#endif
		default:
			break;
    }
}
Пример #9
0
/**
      The macsixlowpanDataRequest function is used to send a frame over
    the air to another node.  Any node type can call this function.

    param:  addr Short address of the destination node.

    param:  len The length of the packet in bytes.

    param:  data Pointer to the data to be sent.

    param:  type Type of frame to be sent
*/
static void
macDataRequestInt(u16 addr, u8 len, u8 * data, u8 type)
{
    // Create a struct pointer to the global variable...
    ftData *data_frame = (ftData*)(mac_buffer_tx+1);
    u8 rpSent; // Was a routing packet sent?


    if (addr == macConfig.shortAddress || addr == BROADCASTADDR)
    {
        // Don't send to self
    	debugMsgStr("\r\nSelf addressed or Brodcast: nothing sent!");
        return;
    }
    if (!macConfig.associated)
        // This node has no short address
        return;
#if DEBUG==2
    debugMsgStr("\r\nmacDataRequest->");
#endif
    // Build the frame.
    data_frame->fcf = FCF_DATA;
    data_frame->seq = macConfig.dsn++;
    data_frame->panid = macConfig.panId;
    data_frame->srcAddr = macConfig.shortAddress;
    data_frame->finalDestAddr = addr;
    data_frame->originAddr = macConfig.shortAddress;

    // send a routing packet if necessary
    rpSent = macSendRoutingPacket(addr);

#if (NODE_TYPE == COORD)
    {
        // Find the child node that can route this packet
        u16 child = addr;
        u16 parent = macGetParent(child);
        while (parent != DEFAULT_COORD_ADDR)
        {
            child = parent;
            parent = macGetParent(child);
        }
        // send to child node that can route this packet
        data_frame->destAddr = child;
    }
#   else
    {
        // All data is send to parent, unless this is a wakeup frame
        if (type == WAKE_NODE)
            data_frame->destAddr = addr;
        else
        	data_frame->destAddr = macConfig.parentShortAddress;
    }
#endif
    // Frame type is data
    data_frame->type = type;

    // Set high bit of type if we're sleeping
    if (macConfig.sleeping && NODE_TYPE == ENDDEVICE && NODE_SLEEP)
       	data_frame->type |= 0x80;  // Indicate that this ENDdevice is sleeping

    // Copy the payload data to frame. (note: this creates smaller code than using memcpy!!)
    u8 i;
    for(i=0; i<len; i++)
        ((u8*)&data_frame->payload)[i] = *data++;

    // Check addresses again - addr will be different now
    if (data_frame->destAddr == macConfig.shortAddress ||
        data_frame->destAddr == BROADCASTADDR)
        // Don't send to self
        return;

    // send data to radio, after some time delay
    *mac_buffer_tx = len + ftDataHeaderSize; // save length away
#if (NODE_TYPE == COORD)
    {
        // See if the child is sleeping (only the coord sends directly to a child node)
        if (NODE_SLEEP && macIsChild(addr) && macIsChildSleeping(addr) )
            // Send it later, after child is awake
            macHoldFrame(addr, (u8*)data_frame, (u8)*mac_buffer_tx);
        else
        {
            // Node is not sleeping child, send it now.
#if DEBUG==2
        	debugMsgStr("-- macSetAlarm set");
#endif
        	macSetAlarm(rpSent ? MAC_RP_DELAY : MAC_DATA_DELAY, mdr_timer);
        }
    }
#  else
        macSetAlarm((type==WAKE_NODE || type == DEBUG_FRAME) ? 0 : MAC_DATA_DELAY, mdr_timer);
#endif
    macConfig.busy = true;
}
Пример #10
0
void nodeSleep(u16 tenthSeconds)
{

    // ************** Power down the other board peripherals
    Leds_off();

    // ************** Power down the radio
    // wait for radio to be done
    u8 state = BUSY_TX_ARET;
    while (state == BUSY_TX_ARET ||
           state == BUSY_RX_AACK)
        state = radioGetTrxState();

    // Now put radio to sleep
    radioEnterSleepMode();


// TODO: figure out what needs to be put to sleep to minimize current consumption
// ************** Power down the on-chip modules
// PRR = 0xbf; ??? 
// Disable ADC
//        ADCSRA &= ~(1 << ADEN);
// Turn off comparator
//        ACSR |= (1 << 
    
// turn off ports  etc

// Turn off BOD

// This should only be done once -- No need to do it over again
/*
        AVR_ENTER_CRITICAL_REGION();
#define BODS  6
#define BODSE 5
        MCUCR  |= (1 << BODSE) | (1<< BODS);
        MCUCR  &= ~(1 << BODSE);
        AVR_LEAVE_CRITICAL_REGION();
    
*/


    // ************** Set the timer to wake up
	// Set TIMER2 Asyncronous Mode.
	ASSR |= (1 << AS2);
	// Set TIMER2 Prescaler to 1024.
	TCCR2B |= ((1 << CS22)|(1 << CS21)|(1 << CS20));
	// Wait for TCNT2 write to finish.
	while(ASSR & (1 << TCR2BUB))
		;


    // Sleep as many times as needed to sleep for the full time
    while (tenthSeconds)
    {
		// This is to get the node manually out of sleeping mode --
    	// Might take up to 7.5Sec to detect button press
    	//
    	if (BUTTON_PRESSED() )
    	{
    		Led1_on();
    		macConfig.sleeping = false;
    		while (BUTTON_PRESSED())
    			;
    		Led1_off();
    		break;		//  exit the Sleeping loop
    	}
		// Set TIMER2 output compare register from user.
		if (tenthSeconds > 75)
		{
			// Just decrement by the max timeout
			OCR2A = 240; // 7.5 seconds, max timeout
			tenthSeconds -= 75;
		}
		else
		{
			// Can measure the remaining time in one timer cycle

			tenthSeconds = tenthSeconds * 16 / 5;
			if (!tenthSeconds)
				tenthSeconds++;
			OCR2A = tenthSeconds;
			tenthSeconds = 0;
		}
		// Wait for OCR2 write to finish.
		while(ASSR & (1 << OCR2AUB))
			;
		// Reset TIMER2 timer counter value.
		TCNT2 = 0;
		// Wait for TCNT2 write to finish before entering sleep.
		while(ASSR & (1 << TCN2UB))
			;

		// Clear interrupt flag
		TIFR2 |= (1 << OCF2A);
		// Enable TIMER2 output compare interrupt.
		TIMSK2 |= (1 << OCIE2A);


        // ************** Go to sleep
        AVR_ENTER_CRITICAL_REGION();
        set_sleep_mode( SLEEP_MODE_PWR_SAVE);
        sleep_enable();
        sei();
        sleep_cpu();   // sleeping right here
        sleep_disable();
        AVR_LEAVE_CRITICAL_REGION();

        wdt_disable();
    }

    // ************** Awake now, wake up everything

 //    PRR = 0x03; ??


    if (SERIAL)
        serial_init(NULL);

    debugMsgStr("\r\nNode slept");
    if ( macConfig.associated)
        HAL_ADC_INIT();

    // Bring SPI port back up (must re-init after sleep)
    radio_spi_init();

    // Wake up radio.
    radioLeaveSleepMode();

    // Set RF212 to 250KB mode.
// TODO: do I need to call this??
    //radioSetup900();

    radioSetTrxState(PLL_ON);
}