/* * 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(); } }