blob: 14ef368d321d780830cb912d49ea936f9d7665ce [file] [log] [blame]
/*
* ======== 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);
}