From 51dfcaa2147d375b9a66c50fd8db8c6f5e6133e4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 1 Jun 2013 08:23:06 -0600 Subject: Add NRF24L01 terminal example. From Laurent Latil. --- apps/ChangeLog.txt | 3 +- apps/examples/Kconfig | 1 + apps/examples/Make.defs | 4 + apps/examples/Makefile | 16 +- apps/examples/nrf24l01_term/Kconfig | 11 + apps/examples/nrf24l01_term/Makefile | 109 +++++++++ apps/examples/nrf24l01_term/nrf24l01_term.c | 356 ++++++++++++++++++++++++++++ 7 files changed, 492 insertions(+), 8 deletions(-) create mode 100644 apps/examples/nrf24l01_term/Kconfig create mode 100644 apps/examples/nrf24l01_term/Makefile create mode 100644 apps/examples/nrf24l01_term/nrf24l01_term.c (limited to 'apps') diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt index 8dc8ce783..f8ba10f72 100644 --- a/apps/ChangeLog.txt +++ b/apps/ChangeLog.txt @@ -570,4 +570,5 @@ ignore to be only the current directory; Ignore .dSYM files in directories where .exe's may be build. Also, in Makefiles, clean .dSYM files in directories where .exe may be built (2013-5-30). - + * apps/examples/nrf35l01_term: Add an example application to demo the + nRF24L01 driver. From Laurent Latil (2013-6-1). diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig index 57671ac4c..2546fea40 100644 --- a/apps/examples/Kconfig +++ b/apps/examples/Kconfig @@ -25,6 +25,7 @@ source "$APPSDIR/examples/modbus/Kconfig" source "$APPSDIR/examples/mount/Kconfig" source "$APPSDIR/examples/mtdpart/Kconfig" source "$APPSDIR/examples/nettest/Kconfig" +source "$APPSDIR/examples/nrf24l01_term/Kconfig" source "$APPSDIR/examples/nsh/Kconfig" source "$APPSDIR/examples/null/Kconfig" source "$APPSDIR/examples/nx/Kconfig" diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs index bb411d4f8..91fb19788 100644 --- a/apps/examples/Make.defs +++ b/apps/examples/Make.defs @@ -126,6 +126,10 @@ ifeq ($(CONFIG_EXAMPLES_NETTEST),y) CONFIGURED_APPS += examples/nettest endif +ifeq ($(CONFIG_EXAMPLES_NRF24L01TERM),y) +CONFIGURED_APPS += examples/nrf24l01_term +endif + ifeq ($(CONFIG_EXAMPLES_NSH),y) CONFIGURED_APPS += examples/nsh endif diff --git a/apps/examples/Makefile b/apps/examples/Makefile index 906e479ac..4c093e129 100644 --- a/apps/examples/Makefile +++ b/apps/examples/Makefile @@ -39,11 +39,12 @@ SUBDIRS = adc buttons can cdcacm composite cxxtest dhcpd discover elf SUBDIRS += flash_test ftpc ftpd hello helloxx hidkbd igmp json keypadtest -SUBDIRS += lcdrw mm modbus mount mtdpart nettest nsh null nx nxconsole nxffs -SUBDIRS += nxflat nxhello nximage nxlines nxtext ostest pashello pipe poll -SUBDIRS += posix_spawn pwm qencoder relays rgmp romfs sendmail serloop slcd -SUBDIRS += smart smart_test tcpecho telnetd thttpd tiff touchscreen udp uip -SUBDIRS += usbserial usbstorage usbterm watchdog wget wgetjson xmlrpc +SUBDIRS += lcdrw mm modbus mount mtdpart nettest nrf24l01_term nsh null +SUBDIRS += nx nxconsole nxffs nxflat nxhello nximage nxlines nxtext ostest +SUBDIRS += pashello pipe poll posix_spawn pwm qencoder relays rgmp romfs +SUBDIRS += sendmail serloop slcd smart smart_test tcpecho telnetd thttpd tiff +SUBDIRS += touchscreen udp uip usbserial usbstorage usbterm watchdog +SUBDIRS += wget wgetjson xmlrpc # Sub-directories that might need context setup. Directories may need # context setup for a variety of reasons, but the most common is because @@ -59,8 +60,9 @@ CNTXTDIRS = pwm ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) CNTXTDIRS += adc can cdcacm composite cxxtest dhcpd discover flash_test ftpd -CNTXTDIRS += hello helloxx json keypadtestmodbus mtdpart nettest nxlines relays -CNTXTDIRS += qencoder slcd smart_test tcpecho telnetd watchdog wgetjson +CNTXTDIRS += hello helloxx json keypadtestmodbus mtdpart nettest nxlines +CNTXTDIRS += nrf24l01_term relays qencoder slcd smart_test tcpecho telnetd +CNTXTDIRS += watchdog wgetjson endif ifeq ($(CONFIG_EXAMPLES_LCDRW_BUILTIN),y) diff --git a/apps/examples/nrf24l01_term/Kconfig b/apps/examples/nrf24l01_term/Kconfig new file mode 100644 index 000000000..59fff2382 --- /dev/null +++ b/apps/examples/nrf24l01_term/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_NRF24L01TERM + bool "Basic nRF24L01 terminal" + default n + +if EXAMPLES_NRF24L01TERM +endif diff --git a/apps/examples/nrf24l01_term/Makefile b/apps/examples/nrf24l01_term/Makefile new file mode 100644 index 000000000..cac8f5a6a --- /dev/null +++ b/apps/examples/nrf24l01_term/Makefile @@ -0,0 +1,109 @@ +############################################################################ +# apps/examples/nrf24l01_term/Makefile +# +# Copyright (C) 2013 Gregory Nutt. 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Basic nRF24L01+ terminal demonstration + +ASRCS = +CSRCS = nrf24l01_term.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ROOTDEPPATH = --dep-path . + +# built-in application info + +APPNAME = nrf24l01_term +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: context clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + @touch .built + +#ifeq ($(CONFIG_EXAMPLES_NXHELLO_BUILTIN),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +#else +#context: +#endif + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep 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 + * + * 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 + +#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; +} -- cgit v1.2.3