nuttx-apps/examples/nrf24l01_term/nrf24l01_term.c

361 lines
9.4 KiB
C
Raw Normal View History

/****************************************************************************
* examples/nrf24l01_term/nrf24l01_term.c
*
* Copyright (C) 2013 Laurent Latil. All rights reserved.
* Author: Laurent Latil <laurent@latil.nom.fr>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <debug.h>
#include <poll.h>
#include <fcntl.h>
#include <nuttx/wireless/nrf24l01.h>
#include "system/readline.h"
#ifdef CONFIG_DISABLE_POLL
# error The poll interface is required for the nRF24L01 terminal example. You must disable config option DISABLE_POLL.
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DEV_NAME "/dev/nrf24l01"
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#define DEFAULT_RADIOFREQ 2450
#define DEFAULT_TXPOWER -6 /* (0, -6, -12, or -18 dBm) */
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
# define N_PFDS 2 /* If RX support is enabled, poll both stdin and the message reception */
#else
# define N_PFDS 1 /* If RX support is not enabled, we cannot poll the wireless device */
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
int wireless_cfg(int fd);
int wireless_open(void);
int send_pkt(int wl_fd);
int read_pkt(int wl_fd);
void usage(void);
/****************************************************************************
* Private Data
****************************************************************************/
static const uint8_t defaultaddr[NRF24L01_MAX_ADDR_LEN] = { 0x01, 0xCA, 0xFE, 0x12, 0x34};
char buff[NRF24L01_MAX_PAYLOAD_LEN + 1] = "";
/* polled file descr */
static struct pollfd pfds[N_PFDS];
/****************************************************************************
* Private Functions
****************************************************************************/
int wireless_cfg(int fd)
{
int error = 0;
uint32_t rf = DEFAULT_RADIOFREQ;
int32_t txpow = DEFAULT_TXPOWER;
nrf24l01_datarate_t datarate = RATE_1Mbps;
nrf24l01_retrcfg_t retrcfg =
{
.count = 5,
.delay = DELAY_1000us
};
uint32_t addrwidth = NRF24L01_MAX_ADDR_LEN;
uint8_t pipes_en = (1 << 0); /* Only pipe #0 is enabled */
nrf24l01_pipecfg_t pipe0cfg;
nrf24l01_pipecfg_t *pipes_cfg[NRF24L01_PIPE_COUNT] = {&pipe0cfg, 0, 0, 0, 0, 0};
nrf24l01_state_t primrxstate;
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
primrxstate = ST_RX;
#else
primrxstate = ST_POWER_DOWN;
#endif
/* Define the pipe #0 parameters (AA enabled, and dynamic payload length) */
pipe0cfg.en_aa = true;
pipe0cfg.payload_length = NRF24L01_DYN_LENGTH;
memcpy (pipe0cfg.rx_addr, defaultaddr, NRF24L01_MAX_ADDR_LEN);
/* Set radio parameters */
ioctl(fd, WLIOC_SETRADIOFREQ, (unsigned long)((uint32_t *)&rf));
ioctl(fd, WLIOC_SETTXPOWER, (unsigned long)((int32_t *)&txpow));
ioctl(fd, NRF24L01IOC_SETDATARATE, (unsigned long)((nrf24l01_datarate_t *)&datarate));
ioctl(fd, NRF24L01IOC_SETRETRCFG, (unsigned long)((nrf24l01_retrcfg_t *)&retrcfg));
ioctl(fd, NRF24L01IOC_SETADDRWIDTH, (unsigned long)((uint32_t*) &addrwidth));
ioctl(fd, NRF24L01IOC_SETTXADDR, (unsigned long)((uint8_t *)&defaultaddr));
ioctl(fd, NRF24L01IOC_SETPIPESCFG, (unsigned long)((nrf24l01_pipecfg_t **)&pipes_cfg));
ioctl(fd, NRF24L01IOC_SETPIPESENABLED, (unsigned long)((uint8_t *)&pipes_en));
/* Enable receiver */
ioctl(fd, NRF24L01IOC_SETSTATE, (unsigned long)((nrf24l01_state_t *)&primrxstate));
return error;
}
int wireless_open(void)
{
int fd;
fd = open(DEV_NAME, O_RDWR);
if (fd < 0)
{
perror("Cannot open nRF24L01 device");
}
else
{
wireless_cfg(fd);
}
return fd;
}
int send_pkt(int wl_fd)
{
int ret;
int len;
/* Remove carriage return */
len = strlen(buff);
if (len > 0 && buff[len - 1] == '\n')
{
len --;
buff[len] = '\0';
}
ret = write(wl_fd, buff, len);
if (ret < 0)
{
perror("Error sending packet");
return ret;
}
else
{
int retrcount;
ioctl(wl_fd, NRF24L01IOC_GETLASTXMITCOUNT, (unsigned long)((uint32_t *)&retrcount));
printf("Packet sent successfully ! (%d retransmitted packets)\n", retrcount);
}
return OK;
}
int read_pkt(int wl_fd)
{
int ret;
uint32_t pipeno;
ret = read(wl_fd, buff, sizeof(buff));
if (ret < 0)
{
perror("Error reading packet\n");
return ret;
}
if (ret == 0)
{
/* Should not happen ... */
printf("Packet payload empty !\n");
return ERROR;
}
/* Get the recipient pipe # (for demo purpose, as here the receiving pipe can only be pipe #0...) */
ioctl(wl_fd, NRF24L01IOC_GETLASTPIPENO, (unsigned long)((uint32_t *)&pipeno));
buff[ret] = '\0'; /* end the string */
printf("Message received : %s (on pipe #%d)\n", buff, pipeno);
return 0;
}
void usage(void)
{
printf("nRF24L01+ wireless terminal demo.\nUsage:\n");
printf("- Type in any message ( <= 32 char length) to send it to communication peer.\n");
printf("- Ctrl-C to exit.\n\n");
}
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int nrf24l01_term_main(int argc, char *argv[])
#endif
{
int ret;
bool quit = false;
int wl_fd;
wl_fd = wireless_open();
if (wl_fd < 0)
{
return -1;
}
usage();
pfds[0].fd = STDIN_FILENO;
pfds[0].events = POLLIN;
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
pfds[1].fd = wl_fd;
pfds[1].events = POLLIN;
#endif
while (!quit)
{
ret = poll(pfds, N_PFDS, -1);
if (ret < 0)
{
perror("Error polling console / wireless");
goto out;
}
if (pfds[0].revents & POLLIN)
{
char c;
read(STDIN_FILENO, &c, 1);
if (c < ' ')
{
/* Any non printable char -> exits */
quit = true;
}
else
{
printf("Message to send > %c", c);
fflush(stdout);
/* Prepend the initial character */
buff[0] = c;
#ifndef CONFIG_SYSTEM_READLINE
/* Use fgets if readline utility method is not enabled */
if (fgets(&buff[1], sizeof(buff) - 1, stdin) == NULL)
{
printf("ERROR: fgets failed: %d\n", errno);
goto out;
}
#else
ret = readline(&buff[1], sizeof(buff) - 1, stdin, stdout);
/* Readline normally returns the number of characters read,
* but will return EOF on end of file or if an error occurs. Either
* will cause the session to terminate.
*/
if (ret == EOF)
{
printf("ERROR: readline failed: %d\n", ret);
goto out;
}
#endif
/* Send content */
send_pkt(wl_fd);
}
}
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
if (!quit && (pfds[1].revents & POLLIN))
{
read_pkt(wl_fd);
}
#endif
}
out:
close(wl_fd);
printf ("Bye !\n");
return 0;
}