| /**************************************************************************** |
| * 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 |
| ****************************************************************************/ |
| |
| #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; |
| } |