| #include <xdc/runtime/System.h> |
| |
| #include "bsp.h" |
| #include "mrfi.h" |
| #include "nwk_types.h" |
| #include "nwk_api.h" |
| #include "bsp_leds.h" |
| #include "bsp_buttons.h" |
| |
| static void linkFrom(void); |
| static void toggleLED(uint8_t which); |
| |
| static uint8_t sRxTid = 0; |
| static linkID_t sLinkID2; |
| static volatile uint8_t sSemaphore = 0; |
| |
| /* Rx callback handler */ |
| static uint8_t sRxCallback(linkID_t); |
| |
| /* |
| * ======== main ======== |
| */ |
| void main(void) |
| { |
| addr_t lAddr = {0x78, 0x56, 0x34, 0x12}; |
| |
| BSP_Init(); |
| |
| /* If an on-the-fly device address is generated it must be done before the |
| * call to SMPL_Init(). If the address is set here the ROM value will not |
| * be used. If SMPL_Init() runs before this IOCTL is used the IOCTL call |
| * will not take effect. One shot only. The IOCTL call below is conformal. |
| */ |
| SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr); |
| |
| /* 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. |
| */ |
| SMPL_Init(sRxCallback); |
| |
| /* turn on LEDs. */ |
| if (!BSP_LED2_IS_ON()) { |
| toggleLED(2); |
| } |
| if (!BSP_LED1_IS_ON()) { |
| toggleLED(1); |
| } |
| |
| /* wait for a button press... */ |
| for (;;) { |
| if (BSP_BUTTON1() || BSP_BUTTON2()) { |
| 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. |
| */ |
| toggleLED(1); |
| |
| /* listen for link forever... */ |
| while (1) { |
| if (SMPL_SUCCESS == SMPL_LinkListen(&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. */ |
| SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); |
| |
| 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; |
| SMPL_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. |
| */ |
| sSemaphore = 0; |
| } |
| } |
| } |
| |
| /* |
| * ======== toggleLED ======== |
| */ |
| static void toggleLED(uint8_t which) |
| { |
| if (1 == which) { |
| BSP_TOGGLE_LED1(); |
| } |
| else if (2 == which) { |
| BSP_TOGGLE_LED2(); |
| } |
| } |
| |
| /* |
| * ======== sRxCallback ======== |
| * handle received messages |
| */ |
| static uint8_t sRxCallback(linkID_t 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 ((SMPL_SUCCESS == SMPL_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 */ |
| toggleLED(msg[0]); |
| sRxTid = tid; |
| } |
| } |
| else { |
| /* wrap case... */ |
| if (sRxTid) { |
| /* we're good. toggle LED */ |
| 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); |
| } |
| |