| /* |
| * ======== listen.c ======== |
| */ |
| #include <xdc/runtime/System.h> |
| #include <local/rf/Radio.h> |
| #include <local/rf/Bsp.h> |
| #include <local/rf/Atomic.h> |
| |
| static uint8_t sRxTid = 0; |
| static Radio_LinkId sLinkID2; |
| static volatile uint8_t sSemaphore = 0; |
| |
| static void linkFrom(void); |
| static uint8_t sRxCallback(Radio_LinkId); /* UART Rx callback handler */ |
| |
| /* |
| * ======== main ======== |
| */ |
| void main(void) |
| { |
| Radio_Addr lAddr = {0x78, 0x56, 0x34, 0x12}; |
| |
| /* If an on-the-fly device address is generated it must be done before the |
| * call to Radio_start(). If the address is set here the ROM value will not |
| * be used. |
| * |
| * This call will fail because the join will fail since there is no |
| * Access Point in this scenario. But we don't care -- just use the |
| * default link token later. |
| * |
| * We supply a callback pointer to handle the message returned by the peer. |
| */ |
| Radio_start(sRxCallback, &lAddr); |
| |
| /* turn on LEDs. */ |
| if (!Bsp_led(2)) { |
| Bsp_toggleLed(2); |
| } |
| if (!Bsp_led(1)) { |
| Bsp_toggleLed(1); |
| } |
| |
| /* wait for a button press... */ |
| for (;;) { |
| Atomic_clear8((Int8 *)&sSemaphore); |
| if (Bsp_button(1) || Bsp_button(2)) { |
| break; |
| } |
| } |
| |
| /* never coming back... */ |
| linkFrom(); |
| |
| /* but in case we do... */ |
| System_abort("returned from linkFrom()!\n"); |
| } |
| |
| /* |
| * ======== linkFrom ======== |
| */ |
| static void linkFrom() |
| { |
| uint8_t msg[2], tid = 0; |
| |
| /* Turn off one LED so we can tell the device is now listening. |
| * Received messages will toggle the other LED. |
| */ |
| Bsp_toggleLed(1); |
| |
| /* listen for link forever... */ |
| while (1) { |
| if (Radio_SUCCESS == Radio_listen(&sLinkID2)) { |
| break; |
| } |
| /* Implement fail-to-link policy here. otherwise, listen again. */ |
| } |
| |
| /* turn on LED1 on the peer in response to receiving a frame. */ |
| msg[0] = 0x01; |
| |
| /* turn on RX. default is RX off. */ |
| Radio_setRxOn(); |
| |
| while (1) { |
| /* Wait for a frame to be received. The Rx handler, which is running |
| * in ISR thread, posts this semaphore allowing the application to |
| * send the reply message in the user thread. |
| */ |
| if (sSemaphore) { |
| msg[1] = ++tid; |
| Radio_send(sLinkID2, msg, sizeof(msg)); |
| |
| /* Reset semaphore. This is not properly protected and there is a |
| * race here. In theory we could miss a message. Good enough for |
| * a demo, though. |
| */ |
| Atomic_clear8((Int8 *)&sSemaphore); |
| } |
| } |
| } |
| |
| /* |
| * ======== sRxCallback ======== |
| * handle received messages |
| */ |
| static uint8_t sRxCallback(Radio_LinkId port) |
| { |
| uint8_t msg[2], len, tid; |
| |
| /* is the callback for the link ID we want to handle? */ |
| if (port == sLinkID2) { |
| /* yes. go get the frame. we know this call will succeed. */ |
| if ((Radio_SUCCESS == Radio_receive(sLinkID2, msg, &len)) && len) { |
| /* Check the application sequence number to detect |
| * late or missing frames... |
| */ |
| tid = msg[1]; |
| if (tid) { |
| if (tid > sRxTid) { |
| /* we're good. toggle LED */ |
| Bsp_toggleLed(msg[0]); |
| sRxTid = tid; |
| } |
| } |
| else { |
| /* wrap case... */ |
| if (sRxTid) { |
| /* we're good. toggle LED */ |
| Bsp_toggleLed(msg[0]); |
| sRxTid = tid; |
| } |
| } |
| |
| /* Post to the semaphore to let application know so it sends |
| * the reply |
| */ |
| sSemaphore = 1; |
| |
| /* drop frame. we're done with it. */ |
| return (1); |
| } |
| } |
| |
| /* keep frame for later handling */ |
| return (0); |
| } |
| |