/**************************************************************************** * examples/nrf24l01_term/nrf24l01_term.c * * Copyright (C) 2013 Laurent Latil. All rights reserved. * Author: Laurent Latil * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "system/readline.h" /**************************************************************************** * 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 main(int argc, FAR 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; }