diff options
Diffstat (limited to 'apps/examples/nrf24l01_term/nrf24l01_term.c')
-rw-r--r-- | apps/examples/nrf24l01_term/nrf24l01_term.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/apps/examples/nrf24l01_term/nrf24l01_term.c b/apps/examples/nrf24l01_term/nrf24l01_term.c new file mode 100644 index 000000000..24d6a23ae --- /dev/null +++ b/apps/examples/nrf24l01_term/nrf24l01_term.c @@ -0,0 +1,356 @@ +/**************************************************************************** + * 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 <apps/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 + ****************************************************************************/ + +int nrf24l01_term_main(int argc, char *argv[]) +{ + 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; +} |