blob: b58643416c4fe9118206ef82c184a5b6db1643c2 [file] [log] [blame]
#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);
}