BaseStationP.nc

/* 
 * BaseStationP bridges packets between a serial channel and the radio.
 * Messages moving from serial to radio will be tagged with the group
 * ID compiled into the TOSBase, and messages moving from radio to
 * serial will be filtered by that same group id.
 */

#include "AM.h"
#include "Serial.h"

module BaseStationP @safe() {
  	uses {
    	interface Boot;
    	interface SplitControl as SerialControl;
    	interface SplitControl as RadioControl;

    	interface AMSend as UartSend[am_id_t id];		//array ?
    	interface Receive as UartReceive[am_id_t id];
    	interface Packet as UartPacket;
    	interface AMPacket as UartAMPacket;
    	
    	interface AMSend as RadioSend[am_id_t id];
    	interface Receive as RadioReceive[am_id_t id];
    	interface Receive as RadioSnoop[am_id_t id];
    	interface Packet as RadioPacket;
    	interface AMPacket as RadioAMPacket;

    	interface Leds;
  	}
} implementation {
  	enum {
    	UART_QUEUE_LEN = 12,
    	RADIO_QUEUE_LEN = 12,
  	};

  	message_t uartQueueBufs[UART_QUEUE_LEN];
  	uint8_t uartIn, uartOut;	//index of in and out
  	bool uartBusy, uartFull;

  	message_t radioQueueBufs[RADIO_QUEUE_LEN];
  	uint8_t radioIn, radioOut;
  	bool radioBusy, radioFull;

  	task void uartSendTask();
  	task void radioSendTask();

  	void dropBlink() {
    	call Leds.led2Toggle();
  	}

  	void failBlink() {
    	call Leds.led2Toggle();
  	}

  	event void Boot.booted() {
    	uartIn = uartOut = 0;
    	uartBusy = FALSE;
    	uartFull = TRUE;
    	radioIn = radioOut = 0;
    	radioBusy = FALSE;
    	radioFull = TRUE;

    	call RadioControl.start();
    	call SerialControl.start();
  	}

  	event void RadioControl.startDone(error_t error) {
    	if (error == SUCCESS) {
      		radioFull = FALSE;
    	}
  	}

  	event void SerialControl.startDone(error_t error) {
    	if (error == SUCCESS) {
      		uartFull = FALSE;
    	}
  	}

  	event void SerialControl.stopDone(error_t error) {
	
	}

  	event void RadioControl.stopDone(error_t error) {
	
	}

  	message_t * ONE receive(message_t * ONE pMsg, void * pPayload, uint8_t payloadLen);	//what's the meaning of "ONE" ?
  
  	event message_t * RadioSnoop.receive[am_id_t id](message_t * pMsg, void * pPayload, uint8_t payloadLen) {
    	return receive(pMsg, pPayload, payloadLen);
  	}
  
  	event message_t * RadioReceive.receive[am_id_t id](message_t * pMsg, void * pPayload, uint8_t payloadLen) {
    	return receive(pMsg, pPayload, payloadLen);
  	}

  	message_t * ONE receive(message_t * ONE pMsg, void * pPayload, uint8_t payloadLen) {
    	message_t * pRet = pMsg;

    	atomic {
      		if (!uartFull) {
	  			pRet = &uartQueueBufs[uartIn];
	  			uartQueueBufs[uartIn] = *pMsg;

				if (uartIn < UART_QUEUE_LEN - 1)
					uartIn++;
				else
					uartIn = 0;
	
	  			if (uartIn == uartOut)
	    			uartFull = TRUE;

	  			if (!uartBusy) {
	    	  		post uartSendTask();
	    	  		uartBusy = TRUE;
	    		}
			}
      		else
				dropBlink();
    	}
    	return pRet;
  	}
  
  	task void uartSendTask() {
    	uint8_t len;
    	am_id_t id;
    	am_addr_t addr, src;
    	message_t * pMsg;
    	atomic {
      		if (uartIn == uartOut && !uartFull)	{
	  			uartBusy = FALSE;
	  			return;
			}
		}
    	pMsg = &uartQueueBufs[uartOut];
    	len = call RadioPacket.payloadLength(pMsg);
    	id = call RadioAMPacket.type(pMsg);
    	addr = call RadioAMPacket.destination(pMsg);
    	src = call RadioAMPacket.source(pMsg);
    	call UartPacket.clear(pMsg);					//!!!
    	call UartAMPacket.setSource(pMsg, src);

    	if (call UartSend.send[id](addr, &uartQueueBufs[uartOut], len) == SUCCESS)
      		call Leds.led1Toggle();
    	else {
			failBlink();
			post uartSendTask();
      	}
  	}

  	event void UartSend.sendDone[am_id_t id](message_t * pMsg, error_t error) {
    	if (error != SUCCESS)
      		failBlink();
    	else
      		atomic
			if (pMsg == &uartQueueBufs[uartOut]) {
				if (uartOut < UART_QUEUE_LEN - 1)
					uartOut++;
				else 
					uartOut = 0;
	      		uartFull = FALSE;
	  		}
    	post uartSendTask();
  	}

  	event message_t * UartReceive.receive[am_id_t id](message_t * pMsg, void * pPayload, uint8_t payloadLen) {
    	message_t * pRet = pMsg;
    	bool reflectToken = FALSE;

    	atomic
      	if (!radioFull) {
	  		reflectToken = TRUE;
	  		pRet = &radioQueueBufs[radioIn];
	  		radioQueueBufs[radioIn] = *pMsg;
			if (radioIn < RADIO_QUEUE_LEN - 1)
				radioIn++;
			else
				radioIn = 0;

	  		if (radioIn == radioOut)
	    		radioFull = TRUE;

	  		if (!radioBusy) {
	      		post radioSendTask();
	      		radioBusy = TRUE;
	    	}
		}
      	else
			dropBlink();

    	if (reflectToken) {
      		//call UartTokenReceive.ReflectToken(Token);
    	}
    	return pRet;
  	}

  	task void radioSendTask() {
    	uint8_t len;
    	am_id_t id;
    	am_addr_t addr, source;
    	message_t * pMsg;
    
    	atomic
    	if (radioIn == radioOut && !radioFull) {
	  		radioBusy = FALSE;
	  		return;
		}

    	pMsg = &radioQueueBufs[radioOut];
    	len = call UartPacket.payloadLength(pMsg);
    	addr = call UartAMPacket.destination(pMsg);
    	source = call UartAMPacket.source(pMsg);
    	id = call UartAMPacket.type(pMsg);

    	call RadioPacket.clear(pMsg);
    	call RadioAMPacket.setSource(pMsg, source);
    
    	if (call RadioSend.send[id](addr, pMsg, len) == SUCCESS)
      		call Leds.led0Toggle();
    	else {
			failBlink();
			post radioSendTask();
      	}
  	}

  	event void RadioSend.sendDone[am_id_t id](message_t * pMsg, error_t error) {
    	if (error != SUCCESS)
      		failBlink();
    	else
      		atomic
			if (pMsg == &radioQueueBufs[radioOut]) {
				if (radioOut < RADIO_QUEUE_LEN - 1)
					radioOut++;
				else
					radioOut = 0;

	      		radioFull = FALSE;
	  		}
    
    	post radioSendTask();
  	}
}  

你可能感兴趣的:(BaseStationP.nc)