You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/09/28 00:43:36 UTC

[10/51] [abbrv] [partial] incubator-mynewt-core git commit: directory re-org, part 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c b/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
new file mode 100644
index 0000000..cf57de6
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
@@ -0,0 +1,400 @@
+/*
+ * 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 <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <assert.h>
+#include <os/os.h>
+#include <bsp/cmsis_nvic.h>
+
+/* Nordic headers */
+#include <nrf.h>
+#include <nrf_adc.h>
+#include <nrf_drv_adc.h>
+#include <app_error.h>
+
+/**
+ * Weak symbol, this is defined in Nordic drivers but not exported.
+ * Needed for NVIC_SetVector().
+ */
+extern void ADC_IRQHandler(void);
+
+#define NRF_ADC_CHANNEL_COUNT   (1)
+
+struct nrf51_adc_stats {
+    uint16_t adc_events;
+    uint16_t adc_events_failed;
+};
+static struct nrf51_adc_stats nrf51_adc_stats;
+
+struct adc_dev *global_adc_dev;
+
+nrf_adc_config_t adc_cfg;
+nrf_drv_adc_config_t *global_adc_config;
+
+struct adc_chan_config nrf51_adc_chans[NRF_ADC_CHANNEL_COUNT];
+nrf_drv_adc_channel_t *nrf_adc_chan;
+
+static void
+nrf51_adc_event_handler(const nrf_drv_adc_evt_t *event)
+{
+    nrf_drv_adc_done_evt_t *done_ev;
+    int rc;
+
+    if (global_adc_dev == NULL) {
+        ++nrf51_adc_stats.adc_events_failed;
+        return;
+    }
+
+    ++nrf51_adc_stats.adc_events;
+
+    /* Right now only data reads supported, assert for unknown event
+     * type.
+     */
+    assert(event->type == NRF_DRV_ADC_EVT_DONE);
+
+    done_ev = (nrf_drv_adc_done_evt_t * const) &event->data.done;
+
+    rc = global_adc_dev->ad_event_handler_func(global_adc_dev,
+            global_adc_dev->ad_event_handler_arg,
+            ADC_EVENT_RESULT, done_ev->p_buffer,
+            done_ev->size * sizeof(nrf_adc_value_t));
+    if (rc != 0) {
+        ++nrf51_adc_stats.adc_events_failed;
+    }
+}
+
+/**
+ * Open the NRF51 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a nrf_drv_saadc_config_t, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf51_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    struct adc_dev *dev;
+    nrf_drv_adc_config_t *cfg;
+    int rc;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+    }
+
+    /* Initialize the device */
+    cfg = (nrf_drv_adc_config_t *)arg;
+    rc = nrf_drv_adc_init(cfg, nrf51_adc_event_handler);
+    if (rc != 0) {
+        goto err;
+    }
+
+    global_adc_dev = dev;
+    global_adc_config = arg;
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+/**
+ * Close the NRF51 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+nrf51_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+
+    dev = (struct adc_dev *) odev;
+
+    nrf_drv_adc_uninit();
+
+    global_adc_dev = NULL;
+    global_adc_config = NULL;
+
+    if (os_started()) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return (0);
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a nrf_drv_adc_channel_config_t
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf51_adc_configure_channel(struct adc_dev *dev, uint8_t cnum,
+                            void *cfgdata)
+{
+    nrf_drv_adc_channel_t *cc;
+    nrf_drv_adc_channel_config_t *cc_cfg;
+    nrf_adc_config_t adc_cfg;
+    uint16_t refmv;
+    uint8_t res;
+    int rc;
+
+    rc = -1;
+    if (global_adc_config == NULL) {
+        goto err;
+    }
+
+    cc = (nrf_drv_adc_channel_t *)cfgdata;
+    nrf_adc_chan = cc;
+    cc_cfg = &cc->config.config;
+
+    adc_cfg.reference = cc_cfg->reference |
+        (cc_cfg->external_reference << ADC_CONFIG_EXTREFSEL_Pos);
+    adc_cfg.resolution = cc_cfg->resolution;
+    adc_cfg.scaling = cc_cfg->input;
+    nrf_adc_configure(&adc_cfg);
+    nrf_drv_adc_channel_enable(cc);
+
+    /* Set the resolution and reference voltage for this channel to
+    * enable conversion functions.
+    */
+    switch (adc_cfg.resolution) {
+        case NRF_ADC_CONFIG_RES_8BIT:
+            res = 8;
+            break;
+        case NRF_ADC_CONFIG_RES_9BIT:
+            res = 9;
+            break;
+        case NRF_ADC_CONFIG_RES_10BIT:
+            res = 10;
+            break;
+        default:
+            assert(0);
+    }
+
+    switch (adc_cfg.reference) {
+        case NRF_ADC_CONFIG_REF_VBG:
+            refmv = 1200; /* 1.2V for NRF51 */
+            break;
+        case NRF_ADC_CONFIG_REF_EXT_REF0:
+            refmv = bsp_get_refmv(cc_cfg);
+            break;
+        case NRF_ADC_CONFIG_REF_EXT_REF1:
+            refmv = bsp_get_refmv(cc_cfg);
+            break;
+        case NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF:
+            refmv = bsp_get_refmv(cc_cfg) / 2;
+            break;
+        case NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD:
+            refmv = bsp_get_refmv(cc_cfg) / 3;
+            break;
+        default:
+            assert(0);
+    }
+
+    /* Adjust reference voltage for gain. */
+    switch (cc_cfg->input) {
+        case NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE:
+            break;
+        case NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD:
+            refmv *= 3;
+            break;
+        case NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS:
+            refmv = (refmv * 3) / 2;
+            break;
+        case NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD:
+            refmv = refmv * 3;
+            break;
+        case NRF_ADC_CONFIG_SCALING_SUPPLY_TWO_THIRDS:
+            refmv = (refmv * 3) / 2;
+            break;
+        default:
+            break;
+    }
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_res = res;
+    dev->ad_chans[cnum].c_refmv = refmv;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Set buffer to read data into.  Implementation of setbuffer handler.
+ * Sets both the primary and secondary buffers for DMA.
+ */
+static int
+nrf51_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2,
+                     int buf_len)
+{
+    int rc;
+
+    /* XXX: If this is called in blocking mode, it will result in a wait. */
+
+    /* Convert overall buffer length, into a total number of samples which
+     * Nordic APIs expect.
+     */
+    buf_len /= sizeof(nrf_adc_value_t);
+
+    rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf1, buf_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    /* XXX: For now, only support one buffer */
+#if 0
+    if (buf2) {
+        rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf2,
+                buf_len);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+#endif
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+nrf51_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    int rc;
+
+    buf_len /= sizeof(nrf_adc_value_t);
+
+    rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf, buf_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+nrf51_adc_sample(struct adc_dev *dev)
+{
+    nrf_drv_adc_sample();
+
+    return (0);
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+nrf51_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    nrf_adc_value_t adc_value;
+    int rc;
+
+    rc = nrf_drv_adc_sample_convert(nrf_adc_chan, &adc_value);
+    if (rc == 0) {
+        *result = (int) adc_value;
+    }
+    return (rc);
+}
+
+static int
+nrf51_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    nrf_adc_value_t val;
+    int data_off;
+
+    data_off = off * sizeof(nrf_adc_value_t);
+    assert(data_off < buf_len);
+
+    val = *(nrf_adc_value_t *) ((uint8_t *) buf + data_off);
+    *result = val;
+
+    return (0);
+}
+
+static int
+nrf51_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return (sizeof(nrf_adc_value_t) * chans * samples);
+}
+
+
+/**
+ * Callback to initialize an adc_dev structure from the os device
+ * initialization callback.  This sets up a nrf51_adc_device(), so that
+ * subsequent lookups to this device allow us to manipulate it.
+ */
+int
+nrf51_adc_dev_init(struct os_dev *odev, void *arg)
+{
+    struct adc_dev *dev;
+    struct adc_driver_funcs *af;
+
+    dev = (struct adc_dev *) odev;
+
+    os_mutex_init(&dev->ad_lock);
+
+    dev->ad_chans = (void *) nrf51_adc_chans;
+    dev->ad_chan_count = NRF_ADC_CHANNEL_COUNT;
+
+    OS_DEV_SETHANDLERS(odev, nrf51_adc_open, nrf51_adc_close);
+
+    af = &dev->ad_funcs;
+
+    af->af_configure_channel = nrf51_adc_configure_channel;
+    af->af_sample = nrf51_adc_sample;
+    af->af_read_channel = nrf51_adc_read_channel;
+    af->af_set_buffer = nrf51_adc_set_buffer;
+    af->af_release_buffer = nrf51_adc_release_buffer;
+    af->af_read_buffer = nrf51_adc_read_buffer;
+    af->af_size_buffer = nrf51_adc_size_buffer;
+
+    NVIC_SetVector(ADC_IRQn, (uint32_t) ADC_IRQHandler);
+
+    return (0);
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h b/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
new file mode 100644
index 0000000..f356f89
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
@@ -0,0 +1,30 @@
+/*
+ * 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 __ADC_NRF52_H__
+#define __ADC_NRF52_H__
+
+#include <adc/adc.h>
+
+#include <nrf.h>
+#include <nrf_saadc.h>
+
+int nrf52_adc_dev_init(struct os_dev *, void *);
+
+#endif /* __ADC_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/pkg.yml b/hw/drivers/adc/adc_nrf52/pkg.yml
new file mode 100644
index 0000000..cd029e5
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/adc/adc_nrf52
+pkg.description: ADC driver for the NRF52
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.apis: 
+    - ADC_HW_IMPL
+pkg.deps:
+   - hw/drivers/adc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
new file mode 100644
index 0000000..d167175
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
@@ -0,0 +1,398 @@
+/*
+ * 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 <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <assert.h>
+#include <os/os.h>
+#include <bsp/cmsis_nvic.h>
+
+/* Nordic headers */
+#include <nrf.h>
+#include <nrf_saadc.h>
+#include <nrf_drv_saadc.h>
+#include <app_error.h>
+
+/**
+ * Weak symbol, this is defined in Nordic drivers but not exported.
+ * Needed for NVIC_SetVector().
+ */
+extern void SAADC_IRQHandler(void);
+
+struct nrf52_saadc_stats {
+    uint16_t saadc_events;
+    uint16_t saadc_events_failed;
+};
+static struct nrf52_saadc_stats nrf52_saadc_stats;
+
+struct adc_dev *global_adc_dev;
+nrf_drv_saadc_config_t *global_adc_config;
+
+uint8_t nrf52_adc_chans[NRF_SAADC_CHANNEL_COUNT * sizeof(struct adc_chan_config)];
+
+static void
+nrf52_saadc_event_handler(const nrf_drv_saadc_evt_t *event)
+{
+    nrf_drv_saadc_done_evt_t *done_ev;
+    int rc;
+
+    if (global_adc_dev == NULL) {
+        ++nrf52_saadc_stats.saadc_events_failed;
+        return;
+    }
+
+    ++nrf52_saadc_stats.saadc_events;
+
+    /* Right now only data reads supported, assert for unknown event
+     * type.
+     */
+    assert(event->type == NRF_DRV_SAADC_EVT_DONE);
+
+    done_ev = (nrf_drv_saadc_done_evt_t * const) &event->data.done;
+
+    rc = global_adc_dev->ad_event_handler_func(global_adc_dev,
+            global_adc_dev->ad_event_handler_arg,
+            ADC_EVENT_RESULT, done_ev->p_buffer,
+            done_ev->size * sizeof(nrf_saadc_value_t));
+    if (rc != 0) {
+        ++nrf52_saadc_stats.saadc_events_failed;
+    }
+}
+
+
+/**
+ * Open the NRF52 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a nrf_drv_saadc_config_t, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf52_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    struct adc_dev *dev;
+    int rc;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+    }
+
+    if (odev->od_flags & OS_DEV_F_STATUS_OPEN) {
+        os_mutex_release(&dev->ad_lock);
+        rc = OS_EBUSY;
+        goto err;
+    }
+
+    /* Initialize the device */
+    rc = nrf_drv_saadc_init((nrf_drv_saadc_config_t *) arg,
+            nrf52_saadc_event_handler);
+    if (rc != 0) {
+        goto err;
+    }
+
+    global_adc_dev = dev;
+    global_adc_config = arg;
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+/**
+ * Close the NRF52 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+nrf52_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+
+    dev = (struct adc_dev *) odev;
+
+    nrf_drv_saadc_uninit();
+
+    global_adc_dev = NULL;
+    global_adc_config = NULL;
+
+    if (os_started()) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return (0);
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a nrf_saadc_channel_config_t
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf52_adc_configure_channel(struct adc_dev *dev, uint8_t cnum,
+        void *cfgdata)
+{
+    nrf_saadc_channel_config_t *cc;
+    uint16_t refmv;
+    uint8_t res;
+    int rc;
+
+    cc = (nrf_saadc_channel_config_t *) cfgdata;
+
+    rc = nrf_drv_saadc_channel_init(cnum, cc);
+    if (rc != 0) {
+        goto err;
+    }
+
+    if (global_adc_config) {
+        /* Set the resolution and reference voltage for this channel to
+        * enable conversion functions.
+        */
+        switch (global_adc_config->resolution) {
+            case NRF_SAADC_RESOLUTION_8BIT:
+                res = 8;
+                break;
+            case NRF_SAADC_RESOLUTION_10BIT:
+                res = 10;
+                break;
+            case NRF_SAADC_RESOLUTION_12BIT:
+                res = 12;
+                break;
+            case NRF_SAADC_RESOLUTION_14BIT:
+                res = 14;
+                break;
+            default:
+                assert(0);
+        }
+    } else {
+        /* Default to 10-bit resolution. */
+        res = 10;
+    }
+
+    switch (cc->reference) {
+        case NRF_SAADC_REFERENCE_INTERNAL:
+            refmv = 600; /* 0.6V for NRF52 */
+            break;
+        case NRF_SAADC_REFERENCE_VDD4:
+            refmv = bsp_get_refmv(NULL) / 4;
+            break;
+        default:
+            assert(0);
+    }
+
+    /* Adjust reference voltage for gain. */
+    switch (cc->gain) {
+        case NRF_SAADC_GAIN1_6:
+            refmv *= 6;
+            break;
+        case NRF_SAADC_GAIN1_5:
+            refmv *= 5;
+            break;
+        case NRF_SAADC_GAIN1_4:
+            refmv *= 4;
+            break;
+        case NRF_SAADC_GAIN1_3:
+            refmv *= 3;
+            break;
+        case NRF_SAADC_GAIN1_2:
+            refmv *= 2;
+            break;
+        case NRF_SAADC_GAIN2:
+            refmv /= 2;
+            break;
+        case NRF_SAADC_GAIN4:
+            refmv /= 4;
+            break;
+        default:
+            break;
+    }
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_res = res;
+    dev->ad_chans[cnum].c_refmv = refmv;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Set buffer to read data into.  Implementation of setbuffer handler.
+ * Sets both the primary and secondary buffers for DMA.
+ */
+static int
+nrf52_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2,
+        int buf_len)
+{
+    int rc;
+
+    /* Convert overall buffer length, into a total number of samples which
+     * Nordic APIs expect.
+     */
+    buf_len /= sizeof(nrf_saadc_value_t);
+
+    rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf1, buf_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    if (buf2) {
+        rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf2,
+                buf_len);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+nrf52_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    int rc;
+
+    buf_len /= sizeof(nrf_saadc_value_t);
+
+    rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf, buf_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+nrf52_adc_sample(struct adc_dev *dev)
+{
+    nrf_drv_saadc_sample();
+
+    return (0);
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+nrf52_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    nrf_saadc_value_t adc_value;
+    int rc;
+
+    rc = nrf_drv_saadc_sample_convert(cnum, &adc_value);
+    if (rc != 0) {
+        goto err;
+    }
+
+    *result = (int) adc_value;
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+nrf52_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+        int *result)
+{
+    nrf_saadc_value_t val;
+    int data_off;
+
+    data_off = off * sizeof(nrf_saadc_value_t);
+    assert(data_off < buf_len);
+
+    val = *(nrf_saadc_value_t *) ((uint8_t *) buf + data_off);
+    *result = val;
+
+    return (0);
+}
+
+static int
+nrf52_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return (sizeof(nrf_saadc_value_t) * chans * samples);
+}
+
+
+/**
+ * Callback to initialize an adc_dev structure from the os device
+ * initialization callback.  This sets up a nrf52_adc_device(), so
+ * that subsequent lookups to this device allow us to manipulate it.
+ */
+int
+nrf52_adc_dev_init(struct os_dev *odev, void *arg)
+{
+    struct adc_dev *dev;
+    struct adc_driver_funcs *af;
+
+    dev = (struct adc_dev *) odev;
+
+    os_mutex_init(&dev->ad_lock);
+
+    dev->ad_chans = (void *) nrf52_adc_chans;
+    dev->ad_chan_count = NRF_SAADC_CHANNEL_COUNT;
+
+    OS_DEV_SETHANDLERS(odev, nrf52_adc_open, nrf52_adc_close);
+
+    af = &dev->ad_funcs;
+
+    af->af_configure_channel = nrf52_adc_configure_channel;
+    af->af_sample = nrf52_adc_sample;
+    af->af_read_channel = nrf52_adc_read_channel;
+    af->af_set_buffer = nrf52_adc_set_buffer;
+    af->af_release_buffer = nrf52_adc_release_buffer;
+    af->af_read_buffer = nrf52_adc_read_buffer;
+    af->af_size_buffer = nrf52_adc_size_buffer;
+
+    NVIC_SetVector(SAADC_IRQn, (uint32_t) SAADC_IRQHandler);
+
+    return (0);
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/include/adc/adc.h
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/include/adc/adc.h b/hw/drivers/adc/include/adc/adc.h
new file mode 100644
index 0000000..2ffb6cd
--- /dev/null
+++ b/hw/drivers/adc/include/adc/adc.h
@@ -0,0 +1,277 @@
+/*
+ * 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 __ADC_H__
+#define __ADC_H__
+
+#include <os/os_dev.h>
+
+struct adc_dev;
+
+/**
+ * Types of ADC events passed to the ADC driver.
+ */
+typedef enum {
+    /* This event represents the result of an ADC run. */
+    ADC_EVENT_RESULT = 0
+} adc_event_type_t;
+
+/**
+ * Event handler for ADC events that are processed in asynchronous mode.
+ *
+ * @param The ADC device being processed
+ * @param The argument data passed to adc_set_result_handler()
+ * @param The event type
+ * @param The buffer containing event data
+ * @param The size in bytes of that buffer.
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_event_handler_func_t)(struct adc_dev *, void *,
+    adc_event_type_t, void *, int);
+
+/**
+ * Configure an ADC channel for this ADC device.  This is implemented
+ * by the HW specific drivers.
+ *
+ * @param The ADC device to configure
+ * @param The channel number to configure
+ * @param An opaque blob containing HW specific configuration.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_configure_channel_func_t)(struct adc_dev *dev, uint8_t,
+        void *);
+
+/**
+ * Trigger a sample on the ADC device asynchronously.  This is implemented
+ * by the HW specific drivers.
+ *
+ * @param The ADC device to sample
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_sample_func_t)(struct adc_dev *);
+
+/**
+ * Blocking read of an ADC channel.  This is implemented by the HW specific
+ * drivers.
+ *
+ * @param The ADC device to perform the blocking read on
+ * @param The channel to read
+ * @param The result to put the ADC reading into
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_read_channel_func_t)(struct adc_dev *, uint8_t, int *);
+
+/**
+ * Set the buffer(s) to read ADC results into for non-blocking reads.  This
+ * is implemented by the HW specific drivers.
+ *
+ * @param The ADC device to read results into
+ * @param The primary buffer to read results into
+ * @param The secondary buffer to read results into (for cases where
+ *        DMA'ing occurs, and secondary buffer can be used while primary
+ *        is being processed.)
+ * @param The length of both buffers in number of bytes
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_set_func_t)(struct adc_dev *, void *, void *, int);
+
+/**
+ * Release a buffer for an ADC device, allowing the driver to re-use it for
+ * DMA'ing data.
+ *
+ * @param The ADC device to release the buffer to
+ * @param A pointer to the buffer to release
+ * @param The length of the buffer being released.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_release_func_t)(struct adc_dev *, void *, int);
+
+/**
+ * Read the next entry from an ADC buffer as a integer
+ *
+ * @param The ADC device to read the entry from
+ * @param The buffer to read the entry from
+ * @param The total length of the buffer
+ * @param The entry number to read from the buffer
+ * @param The result to put the entry into
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_read_func_t)(struct adc_dev *, void *, int, int, int *);
+
+/**
+ * Get the size of a buffer
+ *
+ * @param The ADC device to get the buffer size from
+ * @param The number of channels in the buffer
+ * @param The number of samples in the buffer
+ *
+ * @return The size of the buffer
+ */
+typedef int (*adc_buf_size_func_t)(struct adc_dev *, int, int);
+
+struct adc_driver_funcs {
+    adc_configure_channel_func_t af_configure_channel;
+    adc_sample_func_t af_sample;
+    adc_read_channel_func_t af_read_channel;
+    adc_buf_set_func_t af_set_buffer;
+    adc_buf_release_func_t af_release_buffer;
+    adc_buf_read_func_t af_read_buffer;
+    adc_buf_size_func_t af_size_buffer;
+};
+
+struct adc_chan_config {
+    uint16_t c_refmv;
+    uint8_t c_res;
+    uint8_t c_configured;
+    uint8_t c_cnum;
+};
+
+struct adc_dev {
+    struct os_dev ad_dev;
+    struct os_mutex ad_lock;
+    struct adc_driver_funcs ad_funcs;
+    struct adc_chan_config *ad_chans;
+    int ad_chan_count;
+    adc_event_handler_func_t ad_event_handler_func;
+    void *ad_event_handler_arg;
+};
+
+int adc_chan_config(struct adc_dev *, uint8_t, void *);
+int adc_chan_read(struct adc_dev *, uint8_t, int *);
+int adc_event_handler_set(struct adc_dev *, adc_event_handler_func_t,
+        void *);
+
+/**
+ * Sample the device specified by dev.  This is used in non-blocking mode
+ * to generate samples into the event buffer.
+ *
+ * @param dev The device to sample
+ *
+ * @return 0 on success, non-zero on failure
+ */
+static inline int
+adc_sample(struct adc_dev *dev)
+{
+    return (dev->ad_funcs.af_sample(dev));
+}
+
+/**
+ * Set a result buffer to store data into.  Optionally, provide a
+ * second buffer to continue writing data into as the first buffer
+ * fills up.  Both buffers must be the same size.
+ *
+ * @param dev The ADC device to set the buffer for
+ * @param buf1 The first buffer to spool data into
+ * @param buf2 The second buffer to spool data into, while the first
+ *             buffer is being processed.  If NULL is provided, it's
+ *             unused.
+ * @param buf_len The length of both buffers, in bytes.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static inline int
+adc_buf_set(struct adc_dev *dev, void *buf1, void *buf2,
+        int buf_len)
+{
+    return (dev->ad_funcs.af_set_buffer(dev, buf1, buf2, buf_len));
+}
+
+/**
+ * Release a result buffer on the ADC device, and allow for it to be
+ * re-used for DMA'ing results.
+ *
+ * @param dev The device to release the buffer for
+ * @param buf The buffer to release
+ * @param buf_len The length of the buffer being released.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+static inline int
+adc_buf_release(struct adc_dev *dev, void *buf, int buf_len)
+{
+    return (dev->ad_funcs.af_release_buffer(dev, buf, buf_len));
+}
+
+/**
+ * Read an entry from an ADC buffer
+ *
+ * @param dev The device that the entry is being read from
+ * @param buf The buffer that we're reading the entry from
+ * @param buf_len The length of the buffer we're reading the entry from
+ * @param off The entry number to read from the buffer
+ * @param result A pointer to the result to store the data in
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+static inline int
+adc_buf_read(struct adc_dev *dev, void *buf, int buf_len, int entry,
+        int *result)
+{
+    return (dev->ad_funcs.af_read_buffer(dev, buf, buf_len, entry, result));
+}
+
+/**
+ * Return the size of an ADC buffer
+ *
+ * @param dev The ADC device to return the buffer size from
+ * @param channels The number of channels for these samples
+ * @param samples The number of SAMPLES on this ADC device
+ *
+ * @return The size of the resulting buffer
+ */
+static inline int
+adc_buf_size(struct adc_dev *dev, int chans, int samples)
+{
+    return (dev->ad_funcs.af_size_buffer(dev, chans, samples));
+}
+
+/**
+ * Take an ADC result and convert it to millivolts.
+ *
+ * @param dev The ADC dev to convert the result on
+ * @param cnum The channel number to convert the result from
+ * @param val The ADC value to convert to millivolts
+ *
+ * @return The convert value in millivolts
+ */
+static inline int
+adc_result_mv(struct adc_dev *dev, uint8_t cnum, int val)
+{
+    int res;
+    int refmv;
+    int ret;
+
+    refmv = (int) dev->ad_chans[cnum].c_refmv;
+    res = (int) dev->ad_chans[cnum].c_res;
+
+    ret = val * refmv;
+    ret += (1 << (res - 2));
+    ret = ret >> res;
+
+    return (ret);
+}
+
+#endif /* __ADC_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/pkg.yml b/hw/drivers/adc/pkg.yml
new file mode 100644
index 0000000..9b69134
--- /dev/null
+++ b/hw/drivers/adc/pkg.yml
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/adc
+pkg.description: ADC driver interfaces
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.req_apis:
+    - ADC_HW_IMPL

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/src/adc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/src/adc.c b/hw/drivers/adc/src/adc.c
new file mode 100644
index 0000000..5eb3440
--- /dev/null
+++ b/hw/drivers/adc/src/adc.c
@@ -0,0 +1,89 @@
+/*
+ * 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 <adc/adc.h>
+#include <errno.h>
+#include <assert.h>
+
+/**
+ * Configure a channel on the ADC device.
+ *
+ * @param dev The device to configure
+ * @param cnum The channel number to configure
+ * @param data Driver specific configuration data for this channel.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int
+adc_chan_config(struct adc_dev *dev, uint8_t cnum, void *data)
+{
+    assert(dev->ad_funcs.af_configure_channel != NULL);
+
+    if (cnum > dev->ad_chan_count) {
+        return (EINVAL);
+    }
+
+    return (dev->ad_funcs.af_configure_channel(dev, cnum, data));
+}
+
+/**
+ * Blocking read of an ADC channel.
+ *
+ * @param dev The ADC device to read
+ * @param cnum The channel number to read from that device
+ * @param result Where to put the result of the read
+ *
+ * @return 0 on success, non-zero on error
+ */
+int
+adc_chan_read(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    assert(dev->ad_funcs.af_read_channel != NULL);
+
+    if (cnum > dev->ad_chan_count) {
+        return (EINVAL);
+    }
+
+    if (!dev->ad_chans[cnum].c_configured) {
+        return (EINVAL);
+    }
+
+    return (dev->ad_funcs.af_read_channel(dev, cnum, result));
+}
+
+/**
+ * Set an event handler.  This handler is called for all ADC events.
+ *
+ * @param dev The ADC device to set the event handler for
+ * @param func The event handler function to call
+ * @param arg The argument to pass the event handler function
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+adc_event_handler_set(struct adc_dev *dev, adc_event_handler_func_t func,
+        void *arg)
+{
+    dev->ad_event_handler_func = func;
+    dev->ad_event_handler_arg = arg;
+
+    return (0);
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/include/ble/xcvr.h b/hw/drivers/nimble/native/include/ble/xcvr.h
new file mode 100644
index 0000000..54b580c
--- /dev/null
+++ b/hw/drivers/nimble/native/include/ble/xcvr.h
@@ -0,0 +1,38 @@
+/**
+ * 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 H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS     (140)
+#define XCVR_TX_START_DELAY_USECS     (140)
+#define XCVR_PROC_DELAY_USECS         (100)
+#define XCVR_TX_SCHED_DELAY_USECS     \
+    (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS     \
+    (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE        (0)
+
+#endif /* H_BLE_XCVR_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/pkg.yml b/hw/drivers/nimble/native/pkg.yml
new file mode 100644
index 0000000..bf47e49
--- /dev/null
+++ b/hw/drivers/nimble/native/pkg.yml
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/nimble/native
+pkg.description: BLE driver for simulations.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+    - net/nimble/controller

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/src/ble_hw.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/src/ble_hw.c b/hw/drivers/nimble/native/src/ble_hw.c
new file mode 100644
index 0000000..214ad51
--- /dev/null
+++ b/hw/drivers/nimble/native/src/ble_hw.c
@@ -0,0 +1,225 @@
+/**
+ * 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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_hw.h"
+
+/* Total number of white list elements supported by nrf52 */
+#define BLE_HW_WHITE_LIST_SIZE      (0)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+    g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+    return;
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+    return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+    return;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+    return;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+    return 0;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+    return -1;
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+    return -1;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+    return -1;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+    return -1;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+    return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk   Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+    return 0;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int  Negative values indicate unresolved address; positive values
+ *              indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+    return -1;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/src/ble_phy.c b/hw/drivers/nimble/native/src/ble_phy.c
new file mode 100644
index 0000000..0f1ef5a
--- /dev/null
+++ b/hw/drivers/nimble/native/src/ble_phy.c
@@ -0,0 +1,603 @@
+/**
+ * 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+
+/* BLE PHY data structure */
+struct ble_phy_obj
+{
+    uint8_t phy_stats_initialized;
+    int8_t  phy_txpwr_dbm;
+    uint8_t phy_chan;
+    uint8_t phy_state;
+    uint8_t phy_transition;
+    uint8_t phy_rx_started;
+    uint8_t phy_encrypted;
+    uint8_t phy_privacy;
+    uint8_t phy_tx_pyld_len;
+    uint32_t phy_aar_scratch;
+    uint32_t phy_access_address;
+    struct ble_mbuf_hdr rxhdr;
+    void *txend_arg;
+    uint8_t *rxdptr;
+    ble_phy_tx_end_func txend_cb;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* Statistics */
+struct ble_phy_statistics
+{
+    uint32_t tx_good;
+    uint32_t tx_fail;
+    uint32_t tx_late;
+    uint32_t tx_bytes;
+    uint32_t rx_starts;
+    uint32_t rx_aborts;
+    uint32_t rx_valid;
+    uint32_t rx_crc_err;
+    uint32_t phy_isrs;
+    uint32_t radio_state_errs;
+    uint32_t no_bufs;
+};
+
+struct ble_phy_statistics g_ble_phy_stats;
+
+/* XCVR object to emulate transceiver */
+struct xcvr_data
+{
+    uint32_t irq_status;
+};
+static struct xcvr_data g_xcvr_data;
+
+#define BLE_XCVR_IRQ_F_RX_START     (0x00000001)
+#define BLE_XCVR_IRQ_F_RX_END       (0x00000002)
+#define BLE_XCVR_IRQ_F_TX_START     (0x00000004)
+#define BLE_XCVR_IRQ_F_TX_END       (0x00000008)
+#define BLE_XCVR_IRQ_F_BYTE_CNTR    (0x00000010)
+
+/* "Rail" power level if outside supported range */
+#define BLE_XCVR_TX_PWR_MAX_DBM     (30)
+#define BLE_XCVR_TX_PWR_MIN_DBM     (-20)
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+    STATS_SECT_ENTRY(phy_isrs)
+    STATS_SECT_ENTRY(tx_good)
+    STATS_SECT_ENTRY(tx_fail)
+    STATS_SECT_ENTRY(tx_late)
+    STATS_SECT_ENTRY(tx_bytes)
+    STATS_SECT_ENTRY(rx_starts)
+    STATS_SECT_ENTRY(rx_aborts)
+    STATS_SECT_ENTRY(rx_valid)
+    STATS_SECT_ENTRY(rx_crc_err)
+    STATS_SECT_ENTRY(rx_late)
+    STATS_SECT_ENTRY(no_bufs)
+    STATS_SECT_ENTRY(radio_state_errs)
+    STATS_SECT_ENTRY(rx_hw_err)
+    STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+    STATS_NAME(ble_phy_stats, phy_isrs)
+    STATS_NAME(ble_phy_stats, tx_good)
+    STATS_NAME(ble_phy_stats, tx_fail)
+    STATS_NAME(ble_phy_stats, tx_late)
+    STATS_NAME(ble_phy_stats, tx_bytes)
+    STATS_NAME(ble_phy_stats, rx_starts)
+    STATS_NAME(ble_phy_stats, rx_aborts)
+    STATS_NAME(ble_phy_stats, rx_valid)
+    STATS_NAME(ble_phy_stats, rx_crc_err)
+    STATS_NAME(ble_phy_stats, rx_late)
+    STATS_NAME(ble_phy_stats, no_bufs)
+    STATS_NAME(ble_phy_stats, radio_state_errs)
+    STATS_NAME(ble_phy_stats, rx_hw_err)
+    STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+/* XXX: TODO:
+
+ * 1) Test the following to make sure it works: suppose an event is already
+ * set to 1 and the interrupt is not enabled. What happens if you enable the
+ * interrupt with the event bit already set to 1
+ * 2) how to deal with interrupts?
+ */
+static uint32_t
+ble_xcvr_get_irq_status(void)
+{
+    return g_xcvr_data.irq_status;
+}
+
+static void
+ble_xcvr_clear_irq(uint32_t mask)
+{
+    g_xcvr_data.irq_status &= ~mask;
+}
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+    uint16_t rem_bytes;
+    uint16_t mb_bytes;
+    uint16_t copylen;
+    uint32_t *dst;
+    uint32_t *src;
+    struct os_mbuf *m;
+    struct ble_mbuf_hdr *ble_hdr;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    /* Better be aligned */
+    assert(((uint32_t)dptr & 3) == 0);
+
+    pkthdr = OS_MBUF_PKTHDR(rxpdu);
+    rem_bytes = pkthdr->omp_len;
+
+    /* Fill in the mbuf pkthdr first. */
+    dst = (uint32_t *)(rxpdu->om_data);
+    src = (uint32_t *)dptr;
+
+    mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
+    copylen = min(mb_bytes, rem_bytes);
+    copylen &= 0xFFFC;
+    rem_bytes -= copylen;
+    mb_bytes -= copylen;
+    rxpdu->om_len = copylen;
+    while (copylen > 0) {
+        *dst = *src;
+        ++dst;
+        ++src;
+        copylen -= 4;
+    }
+
+    /* Copy remaining bytes */
+    m = rxpdu;
+    while (rem_bytes > 0) {
+        /* If there are enough bytes in the mbuf, copy them and leave */
+        if (rem_bytes <= mb_bytes) {
+            memcpy(m->om_data + m->om_len, src, rem_bytes);
+            m->om_len += rem_bytes;
+            break;
+        }
+
+        m = SLIST_NEXT(m, om_next);
+        assert(m != NULL);
+
+        mb_bytes = m->om_omp->omp_databuf_len;
+        copylen = min(mb_bytes, rem_bytes);
+        copylen &= 0xFFFC;
+        rem_bytes -= copylen;
+        mb_bytes -= copylen;
+        m->om_len = copylen;
+        dst = (uint32_t *)m->om_data;
+        while (copylen > 0) {
+            *dst = *src;
+            ++dst;
+            ++src;
+            copylen -= 4;
+        }
+    }
+
+    /* Copy ble header */
+    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
+}
+
+void
+ble_phy_isr(void)
+{
+    int rc;
+    uint8_t crcok;
+    uint8_t transition;
+    uint32_t irq_en;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Check for disabled event. This only happens for transmits now */
+    irq_en = ble_xcvr_get_irq_status();
+    if (irq_en & BLE_XCVR_IRQ_F_TX_END) {
+
+        /* Better be in TX state! */
+        assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);
+
+        transition = g_ble_phy_data.phy_transition;
+        if (transition == BLE_PHY_TRANSITION_TX_RX) {
+            /* Disable the phy */
+            /* XXX: count no bufs? */
+            ble_phy_disable();
+        } else {
+            /* Better not be going from rx to tx! */
+            assert(transition == BLE_PHY_TRANSITION_NONE);
+        }
+    }
+
+    /* We get this if we have started to receive a frame */
+    if (irq_en & BLE_XCVR_IRQ_F_RX_START) {
+
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_START);
+
+        /* Call Link Layer receive start function */
+        rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
+                             &g_ble_phy_data.rxhdr);
+        if (rc >= 0) {
+            /* XXX: set rx end enable isr */
+        } else {
+            /* Disable PHY */
+            ble_phy_disable();
+            irq_en = 0;
+            ++g_ble_phy_stats.rx_aborts;
+        }
+
+        /* Count rx starts */
+        ++g_ble_phy_stats.rx_starts;
+    }
+
+    /* Receive packet end (we dont enable this for transmit) */
+    if (irq_en & BLE_XCVR_IRQ_F_RX_END) {
+
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_END);
+
+        /* Construct BLE header before handing up */
+        ble_hdr = &g_ble_phy_data.rxhdr;
+        ble_hdr->rxinfo.flags = 0;
+        ble_hdr->rxinfo.rssi = -77;    /* XXX: dummy rssi */
+        ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+
+        /* Count PHY crc errors and valid packets */
+        crcok = 1;
+        if (!crcok) {
+            ++g_ble_phy_stats.rx_crc_err;
+        } else {
+            ++g_ble_phy_stats.rx_valid;
+            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+        }
+
+        /* Call Link Layer receive payload function */
+        rc = ble_ll_rx_end(g_ble_phy_data.rxdptr, ble_hdr);
+        if (rc < 0) {
+            /* Disable the PHY. */
+            ble_phy_disable();
+        }
+    }
+
+    /* Count # of interrupts */
+    ++g_ble_phy_stats.phy_isrs;
+}
+
+/**
+ * ble phy init
+ *
+ * Initialize the PHY. This is expected to be called once.
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_init(void)
+{
+    /* Set phy channel to an invalid channel so first set channel works */
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+    g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+    /* XXX: emulate ISR? */
+
+    return 0;
+}
+
+int
+ble_phy_rx(void)
+{
+    /* Check radio state */
+    if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+        ble_phy_disable();
+        ++g_ble_phy_stats.radio_state_errs;
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+    return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/**
+ * Called to enable encryption at the PHY. Note that this state will persist
+ * in the PHY; in other words, if you call this function you have to call
+ * disable so that future PHY transmits/receives will not be encrypted.
+ *
+ * @param pkt_counter
+ * @param iv
+ * @param key
+ * @param is_master
+ */
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+                       uint8_t is_master)
+{
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+    /* Set transmit end callback and arg */
+    g_ble_phy_data.txend_cb = txend_cb;
+    g_ble_phy_data.txend_arg = arg;
+}
+
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime)
+{
+    return 0;
+}
+
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_rx_set_start_time(uint32_t cputime)
+{
+    return 0;
+}
+
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
+{
+    int rc;
+    uint32_t state;
+
+    /* Better have a pdu! */
+    assert(txpdu != NULL);
+
+
+    if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+        ble_phy_disable();
+        ++g_ble_phy_stats.radio_state_errs;
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    /* Select tx address */
+    if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
+        /* XXX: fix this */
+        assert(0);
+    } else {
+    }
+
+
+    /* Set the PHY transition */
+    g_ble_phy_data.phy_transition = end_trans;
+
+    /* Make sure transceiver in correct state */
+    state = BLE_PHY_STATE_TX;
+    if (state == BLE_PHY_STATE_TX) {
+        /* Set phy state to transmitting and count packet statistics */
+        g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+        ++g_ble_phy_stats.tx_good;
+        g_ble_phy_stats.tx_bytes += OS_MBUF_PKTHDR(txpdu)->omp_len +
+            BLE_LL_PDU_HDR_LEN;
+        rc = BLE_ERR_SUCCESS;
+    } else {
+        /* Frame failed to transmit */
+        ++g_ble_phy_stats.tx_fail;
+        ble_phy_disable();
+        rc = BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    return rc;
+}
+
+/**
+ * ble phy txpwr set
+ *
+ * Set the transmit output power (in dBm).
+ *
+ * NOTE: If the output power specified is within the BLE limits but outside
+ * the chip limits, we "rail" the power level so we dont exceed the min/max
+ * chip values.
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int 0: success; anything else is an error
+ */
+int
+ble_phy_txpwr_set(int dbm)
+{
+    /* Check valid range */
+    assert(dbm <= BLE_PHY_MAX_PWR_DBM);
+
+    /* "Rail" power level if outside supported range */
+    if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
+        dbm = BLE_XCVR_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
+            dbm = BLE_XCVR_TX_PWR_MIN_DBM;
+        }
+    }
+
+    g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+    return 0;
+}
+
+/**
+ * ble phy txpwr get
+ *
+ * Get the transmit power.
+ *
+ * @return int  The current PHY transmit power, in dBm
+ */
+int
+ble_phy_txpwr_get(void)
+{
+    return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+/**
+ * ble phy setchan
+ *
+ * Sets the logical frequency of the transceiver. The input parameter is the
+ * BLE channel index (0 to 39, inclusive). The NRF52 frequency register
+ * works like this: logical frequency = 2400 + FREQ (MHz).
+ *
+ * Thus, to get a logical frequency of 2402 MHz, you would program the
+ * FREQUENCY register to 2.
+ *
+ * @param chan This is the Data Channel Index or Advertising Channel index
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+    assert(chan < BLE_PHY_NUM_CHANS);
+
+    /* Check for valid channel range */
+    if (chan >= BLE_PHY_NUM_CHANS) {
+        return BLE_PHY_ERR_INV_PARAM;
+    }
+
+    /* Set current access address */
+    if (chan < BLE_PHY_NUM_DATA_CHANS) {
+        g_ble_phy_data.phy_access_address = access_addr;
+    } else {
+        g_ble_phy_data.phy_access_address = BLE_ACCESS_ADDR_ADV;
+    }
+    g_ble_phy_data.phy_chan = chan;
+
+    return 0;
+}
+
+/**
+ * Disable the PHY. This will do the following:
+ *  -> Turn off all phy interrupts.
+ *  -> Disable internal shortcuts.
+ *  -> Disable the radio.
+ *  -> Sets phy state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+/* Gets the current access address */
+uint32_t ble_phy_access_addr_get(void)
+{
+    return g_ble_phy_data.phy_access_address;
+}
+
+/**
+ * Return the phy state
+ *
+ * @return int The current PHY state.
+ */
+int
+ble_phy_state_get(void)
+{
+    return g_ble_phy_data.phy_state;
+}
+
+/**
+ * Called to see if a reception has started
+ *
+ * @return int
+ */
+int
+ble_phy_rx_started(void)
+{
+    return g_ble_phy_data.phy_rx_started;
+}
+
+/**
+ * Called to return the maximum data pdu payload length supported by the
+ * phy. For this chip, if encryption is enabled, the maximum payload is 27
+ * bytes.
+ *
+ * @return uint8_t Maximum data channel PDU payload size supported
+ */
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+    return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+void
+ble_phy_resolv_list_enable(void)
+{
+    g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+    g_ble_phy_data.phy_privacy = 0;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/include/ble/xcvr.h b/hw/drivers/nimble/nrf51/include/ble/xcvr.h
new file mode 100644
index 0000000..7041d8d
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/include/ble/xcvr.h
@@ -0,0 +1,38 @@
+/**
+ * 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 H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS     (140)
+#define XCVR_TX_START_DELAY_USECS     (140)
+#define XCVR_PROC_DELAY_USECS         (100)
+#define XCVR_TX_SCHED_DELAY_USECS     \
+    (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS     \
+    (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE        (8)
+
+#endif /* H_BLE_XCVR_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/pkg.yml b/hw/drivers/nimble/nrf51/pkg.yml
new file mode 100644
index 0000000..6a600cd
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/nimble/nrf51
+pkg.description: BLE driver for nRF51 systems.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+    - net/nimble
+    - net/nimble/controller

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/src/ble_hw.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/src/ble_hw.c b/hw/drivers/nimble/nrf51/src/ble_hw.c
new file mode 100644
index 0000000..259bd05
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/src/ble_hw.c
@@ -0,0 +1,432 @@
+/**
+ * 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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nrf51_bitfields.h"
+#include "controller/ble_hw.h"
+#include "bsp/cmsis_nvic.h"
+
+/* Total number of resolving list elements */
+#define BLE_HW_RESOLV_LIST_SIZE     (16)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Random number generator isr callback */
+ble_rng_isr_cb_t g_ble_rng_isr_cb;
+
+/* If LL privacy is enabled, allocate memory for AAR */
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+
+/* The NRF51 supports up to 16 IRK entries */
+#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
+#define NRF_IRK_LIST_ENTRIES    (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+#else
+#define NRF_IRK_LIST_ENTRIES    (16)
+#endif
+
+/* NOTE: each entry is 16 bytes long. */
+uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
+
+/* Current number of IRK entries */
+uint8_t g_nrf_num_irks;
+
+#endif
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+    NRF_RADIO->DACNF = 0;
+    g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if ((mask & g_ble_hw_whitelist_mask) == 0) {
+            NRF_RADIO->DAB[i] = le32toh(addr);
+            NRF_RADIO->DAP[i] = le16toh(addr + 4);
+            if (addr_type == BLE_ADDR_TYPE_RANDOM) {
+                NRF_RADIO->DACNF |= (mask << 8);
+            }
+            g_ble_hw_whitelist_mask |= mask;
+            return BLE_ERR_SUCCESS;
+        }
+        mask <<= 1;
+    }
+
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint8_t cfg_addr;
+    uint16_t dap;
+    uint16_t txadd;
+    uint32_t dab;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    dab = le32toh(addr);
+    dap = le16toh(addr + 4);
+    txadd = NRF_RADIO->DACNF >> 8;
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if (mask & g_ble_hw_whitelist_mask) {
+            if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
+                cfg_addr = txadd & mask;
+                if (addr_type == BLE_ADDR_TYPE_RANDOM) {
+                    if (cfg_addr != 0) {
+                        break;
+                    }
+                } else {
+                    if (cfg_addr == 0) {
+                        break;
+                    }
+                }
+            }
+        }
+        mask <<= 1;
+    }
+
+    if (i < BLE_HW_WHITE_LIST_SIZE) {
+        g_ble_hw_whitelist_mask &= ~mask;
+        NRF_RADIO->DACNF &= ~mask;
+    }
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+    return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+    /* Enable the configured device addresses */
+    NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+    /* Disable all whitelist devices */
+    NRF_RADIO->DACNF &= 0x0000ff00;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+    return (int)NRF_RADIO->EVENTS_DEVMATCH;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+    int rc;
+    uint32_t end;
+    uint32_t err;
+
+    /* Stop ECB */
+    NRF_ECB->TASKS_STOPECB = 1;
+    /* XXX: does task stop clear these counters? Anyway to do this quicker? */
+    NRF_ECB->EVENTS_ENDECB = 0;
+    NRF_ECB->EVENTS_ERRORECB = 0;
+    NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+
+    /* Start ECB */
+    NRF_ECB->TASKS_STARTECB = 1;
+
+    /* Wait till error or done */
+    rc = 0;
+    while (1) {
+        end = NRF_ECB->EVENTS_ENDECB;
+        err = NRF_ECB->EVENTS_ERRORECB;
+        if (end || err) {
+            if (err) {
+                rc = -1;
+            }
+            break;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Random number generator ISR.
+ */
+static void
+ble_rng_isr(void)
+{
+    uint8_t rnum;
+
+    /* No callback? Clear and disable interrupts */
+    if (g_ble_rng_isr_cb == NULL) {
+        NRF_RNG->INTENCLR = 1;
+        NRF_RNG->EVENTS_VALRDY = 0;
+        (void)NRF_RNG->SHORTS;
+        return;
+    }
+
+    /* If there is a value ready grab it */
+    if (NRF_RNG->EVENTS_VALRDY) {
+        NRF_RNG->EVENTS_VALRDY = 0;
+        rnum = (uint8_t)NRF_RNG->VALUE;
+        (*g_ble_rng_isr_cb)(rnum);
+    }
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+    /* Set bias */
+    if (bias) {
+        NRF_RNG->CONFIG = 1;
+    } else {
+        NRF_RNG->CONFIG = 0;
+    }
+
+    /* If we were passed a function pointer we need to enable the interrupt */
+    if (cb != NULL) {
+        NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
+        NVIC_EnableIRQ(RNG_IRQn);
+        g_ble_rng_isr_cb = cb;
+    }
+
+    return 0;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    if (NRF_RNG->TASKS_START == 0) {
+        NRF_RNG->EVENTS_VALRDY = 0;
+        if (g_ble_rng_isr_cb) {
+            NRF_RNG->INTENSET = 1;
+        }
+        NRF_RNG->TASKS_START = 1;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    NRF_RNG->INTENCLR = 1;
+    NRF_RNG->TASKS_STOP = 1;
+    NRF_RNG->EVENTS_VALRDY = 0;
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+    uint8_t rnum;
+
+    /* Wait for a sample */
+    while (NRF_RNG->EVENTS_VALRDY == 0) {
+    }
+
+    NRF_RNG->EVENTS_VALRDY = 0;
+    rnum = (uint8_t)NRF_RNG->VALUE;
+
+    return rnum;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+    g_nrf_num_irks = 0;
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk   Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+    uint32_t *nrf_entry;
+
+    /* Find first ununsed device address match element */
+    if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    /* Copy into irk list */
+    nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
+    memcpy(nrf_entry, irk, 16);
+
+    /* Add to total */
+    ++g_nrf_num_irks;
+    return BLE_ERR_SUCCESS;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+    uint32_t *irk_entry;
+
+    if (index < g_nrf_num_irks) {
+        --g_nrf_num_irks;
+        irk_entry = &g_nrf_irk_list[index];
+        if (g_nrf_num_irks > index) {
+            memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
+        }
+    }
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+    return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int  Negative values indicate unresolved address; positive values
+ *              indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+    uint32_t index;
+
+    if (NRF_AAR->EVENTS_END) {
+        if (NRF_AAR->EVENTS_RESOLVED) {
+            index = NRF_AAR->STATUS;
+            return (int)index;
+        }
+    }
+
+    return -1;
+}
+#endif