You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2020/12/30 05:13:26 UTC

[incubator-nuttx-apps] branch master updated: added: Using nRF24L01+ as A Bluetooth Low Energy Broadcaster/Beacon

This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 92cfd09  added: Using nRF24L01+ as A Bluetooth Low Energy Broadcaster/Beacon
92cfd09 is described below

commit 92cfd092f761ab5f7ff531e2884a79728e1ca427
Author: yjdwbj <yj...@gmail.com>
AuthorDate: Tue Dec 29 23:11:23 2020 +0800

    added: Using nRF24L01+ as A Bluetooth Low Energy Broadcaster/Beacon
---
 examples/nrf24l01_btle/Kconfig         |  44 +++
 examples/nrf24l01_btle/Make.defs       |  24 ++
 examples/nrf24l01_btle/Makefile        |  34 ++
 examples/nrf24l01_btle/nrf24l01_btle.c | 607 +++++++++++++++++++++++++++++++++
 examples/nrf24l01_btle/nrf24l01_btle.h |  99 ++++++
 5 files changed, 808 insertions(+)

diff --git a/examples/nrf24l01_btle/Kconfig b/examples/nrf24l01_btle/Kconfig
new file mode 100644
index 0000000..99b928d
--- /dev/null
+++ b/examples/nrf24l01_btle/Kconfig
@@ -0,0 +1,44 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config EXAMPLES_NRF24L01_BTLE
+	tristate "Use nRF24L01 emulates a nRF8001 temperature beacon"
+	default n
+	depends on DRIVERS_WIRELESS
+	---help---
+		Emulates a nRF8001 temperature beacon,reads temperature
+		from a DHT11 and sends it via BTLE.Compatible with Nordic
+		Semiconductor apps such as nRF Master Control Panel or
+		nRF Temp 2.0.
+
+if EXAMPLES_NRF24L01_BTLE
+
+config EXAMPLES_NRF24L01_BTLE_PROGNAME
+	string "Program name"
+	default "btle"
+	---help---
+		This is the name of the program that will be used when the NSH ELF
+		program is installed.
+
+config EXAMPLES_NRF24L01_BTLE_PRIORITY
+	int "Dhtxx task priority"
+	default 100
+
+config EXAMPLES_NRF24L01_BTLE_STACKSIZE
+	int "Dhtxx stack size"
+	default DEFAULT_TASK_STACKSIZE
+
+config EXAMPLES_NRF24L01_BTLE_RAND_MAC
+	bool "Use the Rand() to generate MAC"
+	default n
+
+config NRF24L01_BTLE_DHT11
+	tristate "Use the DHTxx humidity/temperature sensor."
+	default n
+	depends on SENSORS_DHTXX
+	---help---
+	    Enable driver support for the DHTxx humidity/temperature sensor.
+
+endif
diff --git a/examples/nrf24l01_btle/Make.defs b/examples/nrf24l01_btle/Make.defs
new file mode 100644
index 0000000..459ce98
--- /dev/null
+++ b/examples/nrf24l01_btle/Make.defs
@@ -0,0 +1,24 @@
+############################################################################
+# apps/examples/nrf24l01_btle/Make.defs
+
+# Adds selected applications to apps/ build
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_EXAMPLES_NRF24L01_BTLE),)
+CONFIGURED_APPS += $(APPDIR)/examples/nrf24l01_btle
+endif
diff --git a/examples/nrf24l01_btle/Makefile b/examples/nrf24l01_btle/Makefile
new file mode 100644
index 0000000..4e1eda4
--- /dev/null
+++ b/examples/nrf24l01_btle/Makefile
@@ -0,0 +1,34 @@
+############################################################################
+# apps/examples/nrf24l01_btle/Makefile
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.  The
+#  ASF licenses this file to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance with the
+#  License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+#  License for the specific language governing permissions and limitations
+#  under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# Basic nRF24L01+ terminal demonstration
+
+MAINSRC = nrf24l01_btle.c
+
+# built-in application info
+
+PROGNAME  = $(CONFIG_EXAMPLES_NRF24L01_BTLE_PROGNAME)
+PRIORITY  = $(CONFIG_EXAMPLES_NRF24L01_BTLE_PRIORITY)
+STACKSIZE = $(CONFIG_EXAMPLES_NRF24L01_BTLE_STACKSIZE)
+MODULE    = $(CONFIG_EXAMPLES_NRF24L01_BTLE)
+
+include $(APPDIR)/Application.mk
diff --git a/examples/nrf24l01_btle/nrf24l01_btle.c b/examples/nrf24l01_btle/nrf24l01_btle.c
new file mode 100644
index 0000000..9916265
--- /dev/null
+++ b/examples/nrf24l01_btle/nrf24l01_btle.c
@@ -0,0 +1,607 @@
+/****************************************************************************
+ * examples/nrf24l01_btle/nrf24l01_btle.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <debug.h>
+
+#include <nuttx/signal.h>
+#include <nuttx/sensors/dhtxx.h>
+#include <nuttx/wireless/nrf24l01.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <poll.h>
+#include <fcntl.h>
+
+#include "nrf24l01_btle.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#define DEV_NAME   "/dev/nrf24l01"
+
+#ifndef STDIN_FILENO
+#  define STDIN_FILENO 0
+#endif
+
+#ifdef CONFIG_DEBUG_WIRELESS
+#  define nrf24_dumpbuffer(m,b,s) lib_dumpbuffer(m,b,s)
+#endif
+
+#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
+/* If RX support is enabled, poll both stdin and the message reception */
+#  define N_PFDS  2
+#else
+/* If RX support is not enabled, we cannot poll the wireless device */
+#  define N_PFDS  1
+#endif
+
+static struct pollfd pfds[N_PFDS];
+#define DEFAULT_TXPOWER    -6    /* (0, -6, -12, or -18 dBm) */
+
+static uint8_t mac[6] =
+  {
+    0x79, 0x6a, 0x64, 0x77, 0x62, 0x6a
+  };
+
+/* logical BTLE channel number (37-39) */
+
+const uint8_t channel[3] =
+  {
+    37, 38, 39
+  };
+
+/* physical frequency (2400+x MHz)  */
+
+const uint8_t frequency[3] =
+  {
+    2, 26, 80
+  };
+
+const uint8_t adve_name[5] =
+  {
+    'n', 'R', 'F', '2', '4'
+  };
+
+struct btle_adv_pdu buffer;
+volatile bool quit;
+
+uint8_t current = 0;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+uint8_t swapbits(uint8_t a)
+{
+  /* reverse the bit order in a single byte */
+
+  uint8_t v = 0;
+  if (a & 0x80) v |= 0x01;
+  if (a & 0x40) v |= 0x02;
+  if (a & 0x20) v |= 0x04;
+  if (a & 0x10) v |= 0x08;
+  if (a & 0x08) v |= 0x10;
+  if (a & 0x04) v |= 0x20;
+  if (a & 0x02) v |= 0x40;
+  if (a & 0x01) v |= 0x80;
+  return v;
+}
+
+/* see BT Core Spec 4.0, Section 6.B.3.2 */
+
+static inline void whiten(uint8_t len)
+{
+  uint8_t i;
+  uint8_t * buf = (uint8_t *)&buffer;
+
+  /* initialize LFSR with current channel, set bit 6 */
+
+  uint8_t lfsr = channel[current] | 0x40;
+
+  while (len--)
+    {
+      uint8_t res = 0;
+
+      /* LFSR in "wire bit order" */
+
+      for (i = 1; i; i <<= 1)
+        {
+          if (lfsr & 0x01)
+            {
+              lfsr ^= 0x88;
+              res |= i;
+            }
+
+          lfsr >>= 1;
+        }
+
+      *(buf++) ^= res;
+    }
+}
+
+/* see BT Core Spec 4.0, Section 6.B.3.1.1 */
+
+static inline void crc(uint8_t len, uint8_t * dst)
+{
+  uint8_t i;
+  uint8_t * buf = (uint8_t *)&buffer;
+
+  /**
+   * initialize 24-bit shift register in "wire bit order"
+   * dst[0] = bits 23-16, dst[1] = bits 15-8, dst[2] = bits 7-0.
+   **/
+
+  dst[0] = 0xaa;
+  dst[1] = 0xaa;
+  dst[2] = 0xaa;
+
+  while (len--)
+    {
+      uint8_t d = *(buf++);
+      for (i = 1; i; i <<= 1, d >>= 1)
+        {
+          /**
+           * save bit 23 (highest-value),
+           * left-shift the entire register by one
+           **/
+
+          uint8_t t = dst[0] & 0x01;         dst[0] >>= 1;
+          if (dst[1] & 0x01) dst[0] |= 0x80; dst[1] >>= 1;
+          if (dst[2] & 0x01) dst[1] |= 0x80; dst[2] >>= 1;
+
+          /**
+           * if the bit just shifted out (former bit 23) and the incoming
+           * data bit are not equal (i.e. bit_out ^ bit_in == 1) => toggle
+           * tap bits
+           */
+
+          if (t != (d & 1))
+            {
+              /**
+               * toggle register tap bits (=XOR with 1)
+               * according to CRC polynom
+               **/
+
+              /* 0b11011010 inv. = 0b01011011 ^= x^6+x^4+x^3+x+1 */
+
+              dst[2] ^= 0xda;
+
+              /* 0b01100000 inv. = 0b00000110 ^= x^10+x^9 */
+
+              dst[1] ^= 0x60;
+            }
+        }
+    }
+}
+
+/* change buffer contents to "wire bit order" */
+
+static inline void swapbuf(uint8_t len)
+{
+  uint8_t * buf = (uint8_t *)&buffer;
+  while (len--)
+    {
+      uint8_t a = *buf;
+      *(buf++) = swapbits(a);
+    }
+}
+
+int nrf24_cfg(int fd)
+{
+  int error = 0;
+
+  uint32_t rf = NRF24L01_MIN_FREQ + frequency[current];
+  int32_t txpow = DEFAULT_TXPOWER;
+
+  /**************************************************************************
+   * if using RATE_1Mbps from include/nuttx/wireless/nrf24l01.h,
+   * tools/checkpatch.sh report error: Mixed case identifier found.
+   *
+   **************************************************************************/
+
+  nrf24l01_datarate_t datarate = 0; /* RATE_1Mbps */
+  nrf24l01_retrcfg_t retrcfg =
+    {
+      .count = 0,
+      .delay = 3 /* DELAY_1000us */
+    };
+
+  uint32_t addrwidth = 4;
+
+  uint8_t pipes_en = (1 << 0);  /* Only pipe #0 is enabled */
+
+  /**************************************************************************
+   * Define the pipe #0 parameters (AA enabled and dynamic payload length).
+   * 4 byte of access address, which is always 0x8E89BED6 for advertizing
+   * packets.
+   *
+   **************************************************************************/
+
+  nrf24l01_pipecfg_t pipe0cfg =
+    {
+     .en_aa = false,
+     .payload_length = 32,
+     .rx_addr =
+        {
+          swapbits(0x8e), swapbits(0x89), swapbits(0xbe), swapbits(0xd6)
+        }
+    };
+
+  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
+
+  /* Set radio parameters */
+
+  ioctl(fd, NRF24L01IOC_SETRETRCFG,
+        (unsigned long)((nrf24l01_retrcfg_t *)&retrcfg));
+
+  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_SETADDRWIDTH,
+        (unsigned long)((uint32_t *)&addrwidth));
+
+  /* set advertisement address: 0x8E89BED6 (bit-reversed -> 0x6B7D9171) */
+
+  ioctl(fd, NRF24L01IOC_SETTXADDR,
+           (unsigned long)((uint8_t *)&pipe0cfg.rx_addr));
+
+  ioctl(fd, NRF24L01IOC_SETPIPESCFG,
+        (unsigned long)((nrf24l01_pipecfg_t **)&pipes_cfg));
+  ioctl(fd, NRF24L01IOC_SETPIPESENABLED,
+        (unsigned long)((uint8_t *)&pipes_en));
+
+  ioctl(fd, NRF24L01IOC_SETSTATE,
+        (unsigned long)((nrf24l01_state_t *)&primrxstate));
+
+  return error;
+}
+
+int nrf24_open(void)
+{
+  int fd;
+
+  fd = open(DEV_NAME, O_RDWR);
+
+  if (fd < 0)
+    {
+      perror("Cannot open nRF24L01 device");
+    }
+  else
+    {
+      nrf24_cfg(fd);
+    }
+
+  return fd;
+}
+
+int nrf24_send(int wl_fd, uint8_t * buf, uint8_t len)
+{
+  int ret;
+
+  wlinfo("send buffer len %d\n", len);
+  ret = write(wl_fd, buf, len);
+  if (ret < 0)
+    {
+      wlerr("Error sending packet\n");
+      return ret;
+    }
+
+  return OK;
+}
+
+static inline void generate_mac(void)
+{
+  srand(time(NULL));
+  mac[0] = 0x42;
+  mac[1] = rand() % 256;
+  mac[2] = rand() % 256;
+  mac[3] = rand() % 256;
+  mac[4] = rand() % 256;
+  mac[5] = rand() % 256;
+}
+
+/****************************************************************************
+ * Broadcast an advertisement packet with a specific data type
+ * Standardized data types can be seen here:
+ * https://www.bluetooth.org/en-us/specification/assigned-
+ * numbers/generic-access-profile
+ *
+ ****************************************************************************/
+
+static void adv_packet(int wl_fd)
+{
+  uint8_t namelen;
+  uint8_t pls = 0;
+  uint8_t i;
+  uint8_t ret;
+#ifdef CONFIG_NRF24L01_BTLE_DHT11
+  int fd;
+  struct dhtxx_sensor_data_s dht_data;
+  struct nrf_service_data *temp;
+  struct nrf_service_data *hum;
+  fd = open("/dev/hum0", O_RDWR);
+#endif
+
+  namelen = sizeof(adve_name);
+
+  /* hop channel */
+
+  ioctl(wl_fd, WLIOC_SETRADIOFREQ,
+        (unsigned long)((uint32_t *)&frequency[current]));
+
+  memcpy(&buffer.mac[0], &mac[0], 6);
+
+  /* add device descriptor chunk */
+
+  chunk(buffer, pls)->size = 0x02;  /* chunk size: 2 */
+  chunk(buffer, pls)->type = 0x01;  /* chunk type: device flags */
+
+  /* flags: LE-only, limited discovery mode */
+
+  chunk(buffer, pls)->data[0] = 0x06;
+  pls += 3;
+
+  /* add device name chunk */
+
+  chunk(buffer, pls)->size = namelen + 1;
+  chunk(buffer, pls)->type = 0x09;
+  for (i = 0; i < namelen; i++)
+    chunk(buffer, pls)->data[i] = adve_name[i];
+  pls += namelen + 2;
+
+  /* add custom data, if applicable */
+
+#ifdef CONFIG_NRF24L01_BTLE_DHT11
+  ret = read(fd, &dht_data, sizeof(struct dhtxx_sensor_data_s));
+  if (ret < 0)
+    {
+      printf("Read error.\n");
+      printf("Sensor reported error %d\n", dht_data.status);
+    }
+
+  /* set temperature */
+
+  chunk(buffer, pls)->size = 3 + 1;  /* chunk size */
+
+  /* chunk type */
+
+  chunk(buffer, pls)->type = 0x16;
+  temp  = chunk(buffer, pls)->data;
+  temp->service_uuid = NRF_TEMPERATURE_SERVICE_UUID;
+  temp->value = (uint8_t)dht_data.temp;
+  pls += 3 + 2;
+
+  /* set humidity  */
+
+  chunk(buffer, pls)->size = 3 + 1;
+  chunk(buffer, pls)->type = 0x16;
+  hum  = chunk(buffer, pls)->data;
+  hum->service_uuid = NRF_ENVIRONMENTAL_SERVICE_UUID;
+  hum->value = (uint8_t)dht_data.hum;
+  pls += 3 + 2;
+#else
+  chunk(buffer, pls)->size = 4 + 1;
+  chunk(buffer, pls)->type = 0xff; /* custom data */
+  chunk(buffer, pls)->data[0] = 't';
+  chunk(buffer, pls)->data[1] = 'e';
+  chunk(buffer, pls)->data[2] = 's';
+  chunk(buffer, pls)->data[3] = 't';
+  pls += 4 + 2;
+  sleep(1);
+#endif
+
+  if (pls > 21)
+    {
+     wlerr("Total payload size must be 21 bytes or less.\n");
+    }
+
+  buffer.payload[pls] = 0x55;
+  buffer.payload[pls + 1] = 0x55;
+  buffer.payload[pls + 2] = 0x55;
+
+  /**************************************************************************
+   * The Payload field consists of AdvA and AdvData fields.
+   * The AdvA field shall  contain the advertiser’s public or
+   * random device address as indicated by TxAdd.
+   * -----------------------------------------------------------
+   * |   PDU  |   Type  |  RFU   | TxAdd  | RxAdd   |Length RFU|
+   * |--------+---------+--------+--------+---------+----------|
+   * |(4 bits)| (2 bits)| (1 bit)| (1 bit)| (6 bits)| (2 bits) |
+   * -----------------------------------------------------------
+   * 0x42 = 0b1000010; include ADV_NONCONN_IND and TxAdd.
+   *
+   **************************************************************************/
+
+  buffer.pdu_type = 0x42;
+
+  /* set final payload size in header include MAC length */
+
+  buffer.pl_size = pls + 6;
+
+  /* calculate CRC over header+MAC+payload, append after payload */
+
+  uint8_t * outbuf = (uint8_t *)&buffer;
+#ifdef CONFIG_DEBUG_WIRELESS
+  syslog(LOG_INFO, "payload len: %d\n ", pls);
+  nrf24_dumpbuffer("Hex Dump", outbuf, sizeof(buffer));
+#endif
+  crc(pls + 8, outbuf + pls + 8);
+  whiten(pls + 11);
+  swapbuf(pls + 11);
+#ifdef CONFIG_NRF24L01_BTLE_DHT11
+  close(fd);
+#endif
+  nrf24_send(wl_fd, (uint8_t *)&buffer, pls + 11);
+}
+
+FAR void *advertise(FAR void *arg)
+{
+  uint32_t wl_fd = *(uint32_t *)arg;
+  while (!quit)
+    {
+      if (current == 2)
+        {
+         current = 0;
+        }
+
+       adv_packet(wl_fd);
+       current++;
+    }
+}
+
+int nrf24_read(int wl_fd)
+{
+  int ret;
+  uint32_t pipeno;
+  uint8_t rbuf[32];
+
+  ret = read(wl_fd, rbuf, sizeof(rbuf));
+  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));
+
+  rbuf[ret] = '\0';   /* end the string */
+
+#ifdef CONFIG_DEBUG_WIRELESS
+  syslog(LOG_INFO, "Message received : (on pipe %d)\n",  pipeno);
+  nrf24_dumpbuffer("Hex Dump", &rbuf[0], 32);
+#endif
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  int ret;
+  struct sched_param param;
+  pthread_t thread;
+  pthread_attr_t attr;
+  char c;
+  int wl_fd;
+  quit = false;
+  current = 0;
+  wl_fd = nrf24_open();
+  if (wl_fd < 0)
+    {
+      return -1;
+    }
+
+#ifdef EXAMPLES_NRF24L01_BTLE_RAND_MAC
+  generate_mac();
+#endif
+  pthread_attr_init(&attr);
+  param.sched_priority = CONFIG_EXAMPLES_NRF24L01_BTLE_PRIORITY;
+  pthread_attr_setschedparam(&attr, &param);
+  pthread_attr_setstacksize(&attr, CONFIG_EXAMPLES_NRF24L01_BTLE_STACKSIZE);
+
+  ret = pthread_create(&thread, &attr, advertise, &wl_fd);
+  if (ret != 0)
+    {
+      printf("nrf24l01_btle: pthread_create failed: %d\n", ret);
+      return ERROR;
+    }
+
+  printf("nRF24L01+ wireless btle demo.\n");
+  printf("For basic Bluetooth Low Energy support using the nRF24L01+\n");
+  printf("sending on the advertising broadcast channel\n");
+  printf("Type 'q' to exit.\n\n");
+
+  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)
+        {
+          read(STDIN_FILENO, &c, 1);
+
+          if (c == 'q')
+            {
+              /* Any non printable char -> exits */
+
+              quit = true;
+              printf ("Bye nRF24l01!\n");
+              sleep(2);
+              goto out;
+            }
+        }
+
+      if (!quit && (pfds[1].revents & POLLIN))
+        {
+          nrf24_read(wl_fd);
+        }
+    }
+
+out:
+  close(wl_fd);
+  return 0;
+}
diff --git a/examples/nrf24l01_btle/nrf24l01_btle.h b/examples/nrf24l01_btle/nrf24l01_btle.h
new file mode 100644
index 0000000..f1d75c2
--- /dev/null
+++ b/examples/nrf24l01_btle/nrf24l01_btle.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+ * examples/nrf24l01_btle/nrf24l01_btle.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __EXAMPLES_NRF24L01_BTLE_H
+#define __EXAMPLES_NRF24L01_BTLE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Service UUIDs used on the nRF8001 and nRF51822 platforms */
+
+#define NRF_TEMPERATURE_SERVICE_UUID		0x1809
+#define NRF_ENVIRONMENTAL_SERVICE_UUID      0x181A
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* helper struct for sending temperature as BT service data */
+
+struct nrf_service_data
+  {
+    int16_t   service_uuid;
+    uint8_t   value;
+  };
+
+/* advertisement PDU */
+
+struct btle_adv_pdu
+  {
+    /* PDU type, most of it 0x42  */
+
+    uint8_t pdu_type;
+
+    /* payload size */
+
+    uint8_t pl_size;
+
+    /* MAC address */
+
+    uint8_t mac[6];
+
+    /* payload (including 3 bytes for CRC) */
+
+    uint8_t payload[24];
+  };
+
+/* payload chunk in advertisement PDU payload */
+
+struct btle_pdu_chunk
+  {
+    uint8_t size;
+    uint8_t type;
+    uint8_t data[];
+  };
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* helper macro to access chunk at specific offset */
+
+#define chunk(x, y) ((struct btle_pdu_chunk *)(x.payload+y))
+
+int nrf24_cfg(int fd);
+
+int nrf24_open(void);
+
+int nrf24_send(int wl_fd, uint8_t * buf, uint8_t len);
+
+#endif /* __EXAMPLES_NRF24L01_BTLE_H  */