/*
* 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
最新推荐文章于 2021-04-28 17:49:43 发布