aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:08:59 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:12:21 +0200
commit3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a (patch)
treeab49cc16ed0b853452c5c2ed2d3042416d628986 /thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers
downloadiot-sensors-master.tar.gz
iot-sensors-master.tar.bz2
iot-sensors-master.tar.xz
iot-sensors-master.zip
o Initial import.HEADmaster
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrf_bitmask.h156
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_adc.h281
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_clock.h223
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_comp.h247
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_gpiote.h423
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_i2s.h254
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_lpcomp.h150
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pdm.h214
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power.h382
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power_clock.h90
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_ppi.h327
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pwm.h497
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qdec.h186
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qspi.h297
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rng.h126
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rtc.h369
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_saadc.h326
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spi.h273
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spim.h396
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spis.h250
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_swi.h222
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_systick.h135
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_timer.h413
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twi.h368
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twim.h408
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twis.h405
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uart.h365
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uarte.h363
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_wdt.h156
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_common.h269
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_errors.h82
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_adc.c324
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_clock.c381
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_comp.c211
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_gpiote.c826
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_i2s.c420
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_lpcomp.c174
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pdm.c370
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power.c306
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power_clock.c52
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_ppi.c534
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pwm.c515
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qdec.c201
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qspi.c337
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rng.c122
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rtc.c348
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c639
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spi.c441
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spim.c688
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spis.c494
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_swi.c412
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_systick.c170
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_timer.c330
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twi.c723
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twim.c664
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twis.c834
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uart.c649
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uarte.c583
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_wdt.c153
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.c166
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.h140
61 files changed, 20860 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrf_bitmask.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrf_bitmask.h
new file mode 100644
index 0000000..8f2ac36
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrf_bitmask.h
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRF_BITMASK_H
+#define NRF_BITMASK_H
+
+#include <nrfx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrf_bitmask Bitmask module
+ * @{
+ * @ingroup nrfx
+ * @brief Bitmask managing module.
+ */
+
+#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8)
+#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007)
+
+/**
+ * Function for checking if bit in the multi-byte bit mask is set.
+ *
+ * @param bit Bit index.
+ * @param p_mask A pointer to mask with bit fields.
+ *
+ * @return 0 if bit is not set, positive value otherwise.
+ */
+__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask)
+{
+ uint8_t const * p_mask8 = (uint8_t const *)p_mask;
+ uint32_t byte_idx = BITMASK_BYTE_GET(bit);
+ bit = BITMASK_RELBIT_GET(bit);
+ return (1 << bit) & p_mask8[byte_idx];
+}
+
+/**
+ * Function for setting a bit in the multi-byte bit mask.
+ *
+ * @param bit Bit index.
+ * @param p_mask A pointer to mask with bit fields.
+ */
+__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask)
+{
+ uint8_t * p_mask8 = (uint8_t *)p_mask;
+ uint32_t byte_idx = BITMASK_BYTE_GET(bit);
+ bit = BITMASK_RELBIT_GET(bit);
+ p_mask8[byte_idx] |= (1 << bit);
+}
+
+/**
+ * Function for clearing a bit in the multi-byte bit mask.
+ *
+ * @param bit Bit index.
+ * @param p_mask A pointer to mask with bit fields.
+ */
+__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask)
+{
+ uint8_t * p_mask8 = (uint8_t *)p_mask;
+ uint32_t byte_idx = BITMASK_BYTE_GET(bit);
+ bit = BITMASK_RELBIT_GET(bit);
+ p_mask8[byte_idx] &= ~(1 << bit);
+}
+
+/**
+ * Function for performing bitwise OR operation on two multi-byte bit masks.
+ *
+ * @param p_mask1 A pointer to the first bit mask.
+ * @param p_mask2 A pointer to the second bit mask.
+ * @param p_out_mask A pointer to the output bit mask.
+ * @param length Length of output mask in bytes.
+ */
+__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1,
+ void const * p_mask2,
+ void * p_out_mask,
+ uint32_t length)
+{
+ uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
+ uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
+ uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
+ uint32_t i;
+ for (i = 0; i < length; i++)
+ {
+ p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i];
+ }
+}
+
+/**
+ * Function for performing bitwise AND operation on two multi-byte bit masks.
+ *
+ * @param p_mask1 A pointer to the first bit mask.
+ * @param p_mask2 A pointer to the second bit mask.
+ * @param p_out_mask A pointer to the output bit mask.
+ * @param length Length of output mask in bytes.
+ */
+__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1,
+ void const * p_mask2,
+ void * p_out_mask,
+ uint32_t length)
+{
+ uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
+ uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
+ uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
+ uint32_t i;
+ for (i = 0; i < length; i++)
+ {
+ p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i];
+ }
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BITMASK_H
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_adc.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_adc.h
new file mode 100644
index 0000000..e28d52a
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_adc.h
@@ -0,0 +1,281 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_ADC_H__
+#define NRFX_ADC_H__
+
+#include <nrfx.h>
+#include <hal/nrf_adc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_adc ADC driver
+ * @{
+ * @ingroup nrf_adc
+ * @brief Analog-to-Digital Converter (ADC) peripheral driver.
+ */
+
+/**
+ * @brief Driver event types.
+ */
+typedef enum
+{
+ NRFX_ADC_EVT_DONE, ///< Event generated when the buffer is filled with samples.
+ NRFX_ADC_EVT_SAMPLE, ///< Event generated when the requested channel is sampled.
+} nrfx_adc_evt_type_t;
+
+/**
+ * @brief Analog-to-digital converter driver DONE event.
+ */
+typedef struct
+{
+ nrf_adc_value_t * p_buffer; ///< Pointer to the buffer with converted samples.
+ uint16_t size; ///< Number of samples in the buffer.
+} nrfx_adc_done_evt_t;
+
+/**
+ * @brief Analog-to-digital converter driver SAMPLE event.
+ */
+typedef struct
+{
+ nrf_adc_value_t sample; ///< Converted sample.
+} nrfx_adc_sample_evt_t;
+
+/**
+ * @brief Analog-to-digital converter driver event.
+ */
+typedef struct
+{
+ nrfx_adc_evt_type_t type; ///< Event type.
+ union
+ {
+ nrfx_adc_done_evt_t done; ///< Data for DONE event.
+ nrfx_adc_sample_evt_t sample; ///< Data for SAMPLE event.
+ } data;
+} nrfx_adc_evt_t;
+
+/**@brief Macro for initializing the ADC channel with the default configuration. */
+#define NRFX_ADC_DEFAULT_CHANNEL(analog_input) \
+ { \
+ NULL, \
+ { \
+ .resolution = NRF_ADC_CONFIG_RES_10BIT, \
+ .scaling = NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE, \
+ .reference = NRF_ADC_CONFIG_REF_VBG, \
+ .input = (analog_input), \
+ .extref = NRF_ADC_CONFIG_EXTREFSEL_NONE \
+ } \
+ }
+
+// Forward declaration of the nrfx_adc_channel_t type.
+typedef struct nrfx_adc_channel_s nrfx_adc_channel_t;
+
+/**
+ * @brief ADC channel.
+ *
+ * This structure is defined by the user and used by the driver. Therefore, it should
+ * not be defined on the stack as a local variable.
+ */
+struct nrfx_adc_channel_s
+{
+ nrfx_adc_channel_t * p_next; ///< Pointer to the next enabled channel (for internal use).
+ nrf_adc_config_t config; ///< ADC configuration for the current channel.
+};
+
+/**
+ * @brief ADC configuration.
+ */
+typedef struct
+{
+ uint8_t interrupt_priority; ///< Priority of ADC interrupt.
+} nrfx_adc_config_t;
+
+/** @brief ADC default configuration. */
+#define NRFX_ADC_DEFAULT_CONFIG \
+{ \
+ .interrupt_priority = NRFX_ADC_CONFIG_IRQ_PRIORITY \
+}
+
+/**
+ * @brief User event handler prototype.
+ *
+ * This function is called when the requested number of samples has been processed.
+ *
+ * @param p_event Event.
+ */
+typedef void (*nrfx_adc_event_handler_t)(nrfx_adc_evt_t const * p_event);
+
+/**
+ * @brief Function for initializing the ADC.
+ *
+ * If a valid event handler is provided, the driver is initialized in non-blocking mode.
+ * If event_handler is NULL, the driver works in blocking mode.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is already initialized.
+ */
+nrfx_err_t nrfx_adc_init(nrfx_adc_config_t const * p_config,
+ nrfx_adc_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the ADC.
+ *
+ * This function stops all ongoing conversions and disables all channels.
+ */
+void nrfx_adc_uninit(void);
+
+/**
+ * @brief Function for enabling an ADC channel.
+ *
+ * This function configures and enables the channel. When @ref nrfx_adc_buffer_convert is
+ * called, all channels that have been enabled with this function are sampled.
+ *
+ * @note The channel instance variable @p p_channel is used by the driver as an item
+ * in a list. Therefore, it cannot be an automatic variable that is located on the stack.
+ */
+void nrfx_adc_channel_enable(nrfx_adc_channel_t * const p_channel);
+
+/**
+ * @brief Function for disabling an ADC channel.
+ */
+void nrfx_adc_channel_disable(nrfx_adc_channel_t * const p_channel);
+
+/**
+ * @brief Function for starting ADC sampling.
+ *
+ * This function triggers single ADC sampling. If more than one channel is enabled, the driver
+ * emulates scanning and all channels are sampled in the order they were enabled.
+ */
+void nrfx_adc_sample(void);
+
+/**
+ * @brief Function for executing a single ADC conversion.
+ *
+ * This function selects the desired input and starts a single conversion. If a valid pointer
+ * is provided for the result, the function blocks until the conversion is completed. Otherwise, the
+ * function returns when the conversion is started, and the result is provided in an event (driver
+ * must be initialized in non-blocking mode, otherwise an assertion will fail). The function will
+ * fail if ADC is busy. The channel does not need to be enabled to perform a single conversion.
+ *
+ * @param[in] p_channel Channel.
+ * @param[out] p_value Pointer to the location where the result should be placed. Unless NULL is
+ * provided, the function is blocking.
+ *
+ * @retval NRFX_SUCCESS If conversion was successful.
+ * @retval NRFX_ERROR_BUSY If the ADC driver is busy.
+ */
+nrfx_err_t nrfx_adc_sample_convert(nrfx_adc_channel_t const * const p_channel,
+ nrf_adc_value_t * p_value);
+
+/**
+ * @brief Function for converting data to the buffer.
+ *
+ * If the driver is initialized in non-blocking mode, this function returns when the first
+ * conversion is set up. When the buffer is filled, the application is notified by the event
+ * handler. If the driver is initialized in blocking mode, the function returns when the buffer is
+ * filled.
+ *
+ * Conversion is done on all enabled channels, but it is not triggered by this
+ * function. This function will prepare the ADC for sampling and then
+ * wait for the SAMPLE task. Sampling can be triggered manually by the @ref
+ * nrfx_adc_sample function or by PPI using the @ref NRF_ADC_TASK_START task.
+ *
+ * @note If more than one channel is enabled, the function emulates scanning, and
+ * a single START task will trigger conversion on all enabled channels. For example:
+ * If 3 channels are enabled and the user requests 6 samples, the completion event
+ * handler will be called after 2 START tasks.
+ *
+ * @note The application must adjust the sampling frequency. The maximum frequency
+ * depends on the sampling timer and the maximum latency of the ADC interrupt. If
+ * an interrupt is not handled before the next sampling is triggered, the sample
+ * will be lost.
+ *
+ * @param[in] buffer Result buffer.
+ * @param[in] size Buffer size in samples.
+ *
+ * @retval NRFX_SUCCESS If conversion was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is busy.
+ */
+nrfx_err_t nrfx_adc_buffer_convert(nrf_adc_value_t * buffer, uint16_t size);
+
+/**
+ * @brief Function for retrieving the ADC state.
+ *
+ * @retval true If the ADC is busy.
+ * @retval false If the ADC is ready.
+ */
+bool nrfx_adc_is_busy(void);
+
+/**
+ * @brief Function for getting the address of the ADC START task.
+ *
+ * This function is used to get the address of the START task, which can be used to trigger ADC
+ * conversion.
+ *
+ * @return Start task address.
+ */
+__STATIC_INLINE uint32_t nrfx_adc_start_task_get(void);
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE uint32_t nrfx_adc_start_task_get(void)
+{
+ return nrf_adc_task_address_get(NRF_ADC_TASK_START);
+}
+
+#endif
+
+
+void nrfx_adc_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_ADC_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_clock.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_clock.h
new file mode 100644
index 0000000..8a5e184
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_clock.h
@@ -0,0 +1,223 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_CLOCK_H__
+#define NRFX_CLOCK_H__
+
+#include <nrfx.h>
+#include <hal/nrf_clock.h>
+#include <nrfx_power_clock.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_clock CLOCK driver
+ * @{
+ * @ingroup nrf_clock
+ * @brief CLOCK peripheral driver.
+ */
+
+/**
+ * @brief Clock events.
+ */
+typedef enum
+{
+ NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
+ NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
+ NRFX_CLOCK_EVT_CTTO, ///< Calibration timeout.
+ NRFX_CLOCK_EVT_CAL_DONE ///< Calibration has been done.
+} nrfx_clock_evt_type_t;
+
+/**
+ * @brief Clock event handler.
+ *
+ * @param[in] event Event.
+ */
+typedef void (*nrfx_clock_event_handler_t)(nrfx_clock_evt_type_t event);
+
+/**
+ * @brief Function for initializing internal structures in the nrfx_clock module.
+ *
+ * After initialization, the module is in power off state (clocks are not started).
+ *
+ * @param[in] event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_ALREADY_INITIALIZED If the driver was already initialized.
+ */
+nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler);
+
+/**
+ * @brief Function for enabling interrupts in the clock module.
+ */
+void nrfx_clock_enable(void);
+
+/**
+ * @brief Function for disabling interrupts in the clock module.
+ */
+void nrfx_clock_disable(void);
+
+/**
+ * @brief Function for uninitializing the clock module.
+ */
+void nrfx_clock_uninit(void);
+
+/**
+ * @brief Function for starting the LFCLK.
+ */
+void nrfx_clock_lfclk_start(void);
+
+/**
+ * @brief Function for stoping the LFCLK.
+ */
+void nrfx_clock_lfclk_stop(void);
+
+/**
+ * @brief Function for checking the LFCLK state.
+ *
+ * @retval true If the LFCLK is running.
+ * @retval false If the LFCLK is not running.
+ */
+__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void);
+
+/**
+ * @brief Function for starting the high-accuracy source HFCLK.
+ */
+void nrfx_clock_hfclk_start(void);
+
+/**
+ * @brief Function for stoping external high-accuracy source HFCLK.
+ */
+void nrfx_clock_hfclk_stop(void);
+
+/**
+ * @brief Function for checking the HFCLK state.
+ *
+ * @retval true If the HFCLK is running (XTAL source).
+ * @retval false If the HFCLK is not running.
+ */
+__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void);
+
+/**
+ * @brief Function for starting calibration of internal LFCLK.
+ *
+ * This function starts the calibration process. The process cannot be aborted. LFCLK and HFCLK
+ * must be running before this function is called.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the low-frequency of high-frequency clock is off.
+ * @retval NRFX_ERROR_BUSY If calibration is in progress.
+ */
+nrfx_err_t nrfx_clock_calibration_start(void);
+
+/**
+ * @brief Function for checking if calibration is in progress.
+ *
+ * This function indicates that the system is in calibration phase.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If calibration is in progress.
+ */
+nrfx_err_t nrfx_clock_is_calibrating(void);
+
+/**
+ * @brief Function for starting calibration timer.
+ * @param interval Time after which the CTTO event and interrupt will be generated (in 0.25 s units).
+ */
+void nrfx_clock_calibration_timer_start(uint8_t interval);
+
+/**
+ * @brief Function for stoping calibration timer.
+ */
+void nrfx_clock_calibration_timer_stop(void);
+
+/**@brief Function for returning a requested task address for the clock driver module.
+ *
+ * @param[in] task One of the peripheral tasks.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task);
+
+/**@brief Function for returning a requested event address for the clock driver module.
+ *
+ * @param[in] event One of the peripheral events.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task)
+{
+ return nrf_clock_task_address_get(task);
+}
+
+__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event)
+{
+ return nrf_clock_event_address_get(event);
+}
+
+__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void)
+{
+ return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
+}
+
+__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void)
+{
+ return nrf_clock_lf_is_running();
+}
+#endif //SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_clock_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_CLOCK_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_comp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_comp.h
new file mode 100644
index 0000000..8b4ee44
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_comp.h
@@ -0,0 +1,247 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_COMP_H__
+#define NRFX_COMP_H__
+
+#include <nrfx.h>
+#include <hal/nrf_comp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_comp COMP driver
+ * @{
+ * @ingroup nrf_comp
+ * @brief Comparator (COMP) peripheral driver.
+ */
+
+/**
+ * @brief Macro to convert the threshold voltage to an integer value
+ * (needed by the COMP_TH register).
+ *
+ * @param[in] vol Voltage to be changed to COMP_TH register value. This value
+ * must not be smaller than reference voltage divided by 64.
+ * @param[in] ref Reference voltage.
+ */
+#define NRFX_VOLTAGE_THRESHOLD_TO_INT(vol, ref) \
+ (uint8_t)(((vol) > ((ref) / 64)) ? (NRFX_ROUNDED_DIV((vol) * 64,(ref)) - 1) : 0)
+
+/**
+ * @brief COMP event handler function type.
+ * @param[in] event COMP event.
+ */
+typedef void (* nrfx_comp_event_handler_t)(nrf_comp_event_t event);
+
+/** @brief COMP shortcut masks. */
+typedef enum
+{
+ NRFX_COMP_SHORT_STOP_AFTER_CROSS_EVT = COMP_SHORTS_CROSS_STOP_Msk, /*!< Shortcut between the CROSS event and the STOP task. */
+ NRFX_COMP_SHORT_STOP_AFTER_UP_EVT = COMP_SHORTS_UP_STOP_Msk, /*!< Shortcut between the UP event and the STOP task. */
+ NRFX_COMP_SHORT_STOP_AFTER_DOWN_EVT = COMP_SHORTS_DOWN_STOP_Msk /*!< Shortcut between the DOWN event and the STOP task. */
+} nrfx_comp_short_mask_t;
+
+/** @brief COMP events masks. */
+typedef enum
+{
+ NRFX_COMP_EVT_EN_CROSS_MASK = COMP_INTENSET_CROSS_Msk, /*!< CROSS event (generated after VIN+ == VIN-). */
+ NRFX_COMP_EVT_EN_UP_MASK = COMP_INTENSET_UP_Msk, /*!< UP event (generated when VIN+ crosses VIN- while increasing). */
+ NRFX_COMP_EVT_EN_DOWN_MASK = COMP_INTENSET_DOWN_Msk, /*!< DOWN event (generated when VIN+ crosses VIN- while decreasing). */
+ NRFX_COMP_EVT_EN_READY_MASK = COMP_INTENSET_READY_Msk /*!< READY event (generated when the module is ready). */
+} nrfx_comp_evt_en_mask_t;
+
+/** @brief COMP configuration. */
+typedef struct
+{
+ nrf_comp_ref_t reference; /**< Reference selection. */
+ nrf_comp_ext_ref_t ext_ref; /**< External analog reference selection. */
+ nrf_comp_main_mode_t main_mode; /**< Main operation mode. */
+ nrf_comp_th_t threshold; /**< Structure holding THDOWN and THUP values needed by the COMP_TH register. */
+ nrf_comp_sp_mode_t speed_mode; /**< Speed and power mode. */
+ nrf_comp_hyst_t hyst; /**< Comparator hysteresis.*/
+#if defined (COMP_ISOURCE_ISOURCE_Msk) || defined (__NRFX_DOXYGEN__)
+ nrf_isource_t isource; /**< Current source selected on analog input. */
+#endif
+ nrf_comp_input_t input; /**< Input to be monitored. */
+ uint8_t interrupt_priority; /**< Interrupt priority. */
+} nrfx_comp_config_t;
+
+/** @brief COMP threshold default configuration. */
+#define NRFX_COMP_CONFIG_TH \
+{ \
+ .th_down = NRFX_VOLTAGE_THRESHOLD_TO_INT(0.5, 1.8), \
+ .th_up = NRFX_VOLTAGE_THRESHOLD_TO_INT(1.5, 1.8) \
+}
+
+/** @brief COMP driver default configuration including the COMP HAL configuration. */
+#if defined (COMP_ISOURCE_ISOURCE_Msk) || defined (__NRFX_DOXYGEN__)
+#define NRFX_COMP_DEFAULT_CONFIG(_input) \
+{ \
+ .reference = (nrf_comp_ref_t)NRFX_COMP_CONFIG_REF, \
+ .main_mode = (nrf_comp_main_mode_t)NRFX_COMP_CONFIG_MAIN_MODE, \
+ .threshold = NRFX_COMP_CONFIG_TH, \
+ .speed_mode = (nrf_comp_sp_mode_t)NRFX_COMP_CONFIG_SPEED_MODE, \
+ .hyst = (nrf_comp_hyst_t)NRFX_COMP_CONFIG_HYST, \
+ .isource = (nrf_isource_t)NRFX_COMP_CONFIG_ISOURCE, \
+ .input = (nrf_comp_input_t)_input, \
+ .interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY \
+}
+#else
+#define NRFX_COMP_DEFAULT_CONFIG(_input) \
+{ \
+ .reference = (nrf_comp_ref_t)NRFX_COMP_CONFIG_REF, \
+ .main_mode = (nrf_comp_main_mode_t)NRFX_COMP_CONFIG_MAIN_MODE, \
+ .threshold = NRFX_COMP_CONFIG_TH, \
+ .speed_mode = (nrf_comp_sp_mode_t)NRFX_COMP_CONFIG_SPEED_MODE, \
+ .hyst = (nrf_comp_hyst_t)NRFX_COMP_CONFIG_HYST, \
+ .input = (nrf_comp_input_t)_input, \
+ .interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY \
+}
+#endif
+
+/**
+ * @brief Function for initializing the COMP driver.
+ *
+ * This function initializes the COMP driver, but does not enable the peripheral or any interrupts.
+ * To start the driver, call the function @ref nrfx_comp_start() after initialization.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver has already been initialized.
+ * @retval NRFX_ERROR_BUSY If the LPCOMP peripheral is already in use.
+ * This is possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_comp_init(nrfx_comp_config_t const * p_config,
+ nrfx_comp_event_handler_t event_handler);
+
+
+/**
+ * @brief Function for uninitializing the COMP driver.
+ *
+ * This function uninitializes the COMP driver. The COMP peripheral and
+ * its interrupts are disabled, and local variables are cleaned. After this call, you must
+ * initialize the driver again by calling nrfx_comp_init() if you want to use it.
+ *
+ * @sa nrfx_comp_stop()
+ */
+void nrfx_comp_uninit(void);
+
+/**
+ * @brief Function for setting the analog input.
+ *
+ * @param[in] psel COMP analog pin selection.
+ */
+void nrfx_comp_pin_select(nrf_comp_input_t psel);
+
+/**
+ * @brief Function for starting the COMP peripheral and interrupts.
+ *
+ * Before calling this function, the driver must be initialized. This function
+ * enables the COMP peripheral and its interrupts.
+ *
+ * @param[in] comp_evt_en_mask Mask of events to be enabled. This parameter should be built as
+ * 'or' of elements from @ref nrfx_comp_evt_en_mask_t.
+ * @param[in] comp_shorts_mask Mask of shorts to be enabled. This parameter should be built as
+ * 'or' of elements from @ref nrfx_comp_short_mask_t.
+ *
+ * @sa nrfx_comp_init()
+ *
+ */
+void nrfx_comp_start(uint32_t comp_evt_en_mask, uint32_t comp_shorts_mask);
+
+/**@brief Function for stopping the COMP peripheral.
+ *
+ * Before calling this function, the driver must be enabled. This function disables the COMP
+ * peripheral and its interrupts.
+ *
+ * @sa nrfx_comp_uninit()
+ *
+ */
+void nrfx_comp_stop(void);
+
+/**
+ * @brief Function for copying the current state of the comparator result to the RESULT register.
+ *
+ * @retval 0 If the input voltage is below the threshold (VIN+ < VIN-).
+ * @retval 1 If the input voltage is above the threshold (VIN+ > VIN-).
+ */
+uint32_t nrfx_comp_sample(void);
+
+/**
+ * @brief Function for getting the address of a COMP task.
+ *
+ * @param[in] task COMP task.
+ *
+ * @return Address of the given COMP task.
+ */
+__STATIC_INLINE uint32_t nrfx_comp_task_address_get(nrf_comp_task_t task)
+{
+ return (uint32_t)nrf_comp_task_address_get(task);
+}
+
+/**
+ * @brief Function for getting the address of a COMP event.
+ *
+ * @param[in] event COMP event.
+ *
+ * @return Address of the given COMP event.
+ */
+__STATIC_INLINE uint32_t nrfx_comp_event_address_get(nrf_comp_event_t event)
+{
+ return (uint32_t)nrf_comp_event_address_get(event);
+}
+
+
+void nrfx_comp_irq_handler(void);
+
+
+/** @} **/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_COMP_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_gpiote.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_gpiote.h
new file mode 100644
index 0000000..ee79e6d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_gpiote.h
@@ -0,0 +1,423 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_GPIOTE_H__
+#define NRFX_GPIOTE_H__
+
+#include <nrfx.h>
+#include <hal/nrf_gpiote.h>
+#include <hal/nrf_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_gpiote GPIOTE driver
+ * @{
+ * @ingroup nrf_gpiote
+ * @brief GPIOTE peripheral driver.
+ */
+
+/**@brief Input pin configuration. */
+typedef struct
+{
+ nrf_gpiote_polarity_t sense; /**< Transition that triggers interrupt. */
+ nrf_gpio_pin_pull_t pull; /**< Pulling mode. */
+ bool is_watcher : 1; /**< True when the input pin is tracking an output pin. */
+ bool hi_accuracy : 1; /**< True when high accuracy (IN_EVENT) is used. */
+ bool skip_gpio_setup : 1; /**< Do not change GPIO configuration */
+} nrfx_gpiote_in_config_t;
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition.
+ * @details Set hi_accu to true to use IN_EVENT. */
+#define NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_LOTOHI, \
+ }
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition.
+ * @details Set hi_accu to true to use IN_EVENT. */
+#define NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_HITOLO, \
+ }
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin.
+ * @details Set hi_accu to true to use IN_EVENT.*/
+#define NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_TOGGLE, \
+ }
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition.
+ * @details Set hi_accu to true to use IN_EVENT.
+ * @note This macro prepares configuration that skips GPIO setup. */
+#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_LOTOHI, \
+ .skip_gpio_setup = true, \
+ }
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition.
+ * @details Set hi_accu to true to use IN_EVENT.
+ * @note This macro prepares configuration that skips GPIO setup. */
+#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_HITOLO, \
+ .skip_gpio_setup = true, \
+ }
+
+/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin.
+ * @details Set hi_accu to true to use IN_EVENT.
+ * @note This macro prepares configuration that skips GPIO setup. */
+#define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE(hi_accu) \
+ { \
+ .is_watcher = false, \
+ .hi_accuracy = hi_accu, \
+ .pull = NRF_GPIO_PIN_NOPULL, \
+ .sense = NRF_GPIOTE_POLARITY_TOGGLE, \
+ .skip_gpio_setup = true, \
+ }
+
+
+/**@brief Output pin configuration. */
+typedef struct
+{
+ nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */
+ nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */
+ bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */
+} nrfx_gpiote_out_config_t;
+
+/**@brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */
+#define NRFX_GPIOTE_CONFIG_OUT_SIMPLE(init_high) \
+ { \
+ .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
+ .task_pin = false, \
+ }
+
+/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low.
+ * @details The task will clear the pin. Therefore, the pin is set initially. */
+#define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW \
+ { \
+ .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \
+ .task_pin = true, \
+ .action = NRF_GPIOTE_POLARITY_HITOLO, \
+ }
+
+/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high.
+ * @details The task will set the pin. Therefore, the pin is cleared initially. */
+#define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH \
+ { \
+ .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \
+ .task_pin = true, \
+ .action = NRF_GPIOTE_POLARITY_LOTOHI, \
+ }
+
+/**@brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state.
+ * @details The initial pin state must be provided. */
+#define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \
+ { \
+ .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
+ .task_pin = true, \
+ .action = NRF_GPIOTE_POLARITY_TOGGLE, \
+ }
+
+/** @brief Pin. */
+typedef uint32_t nrfx_gpiote_pin_t;
+
+/**
+ * @brief Pin event handler prototype.
+ *
+ * @param pin Pin that triggered this event.
+ * @param action Action that lead to triggering this event.
+ */
+typedef void (*nrfx_gpiote_evt_handler_t)(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
+
+/**
+ * @brief Function for initializing the GPIOTE module.
+ *
+ * @details Only static configuration is supported to prevent the shared
+ * resource being customized by the initiator.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ */
+nrfx_err_t nrfx_gpiote_init(void);
+
+/**
+ * @brief Function for checking if the GPIOTE module is initialized.
+ *
+ * @details The GPIOTE module is a shared module. Therefore, you should check if
+ * the module is already initialized and skip initialization if it is.
+ *
+ * @retval true If the module is already initialized.
+ * @retval false If the module is not initialized.
+ */
+bool nrfx_gpiote_is_init(void);
+
+/**
+ * @brief Function for uninitializing the GPIOTE module.
+ */
+void nrfx_gpiote_uninit(void);
+
+/**
+ * @brief Function for initializing a GPIOTE output pin.
+ * @details The output pin can be controlled by the CPU or by PPI. The initial
+ * configuration specifies which mode is used. If PPI mode is used, the driver
+ * attempts to allocate one of the available GPIOTE channels. If no channel is
+ * available, an error is returned.
+ *
+ * @param[in] pin Pin.
+ * @param[in] p_config Initial configuration.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used.
+ * @retval NRFX_ERROR_NO_MEM If no GPIOTE channel is available.
+ */
+nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,
+ nrfx_gpiote_out_config_t const * p_config);
+
+/**
+ * @brief Function for uninitializing a GPIOTE output pin.
+ * @details The driver frees the GPIOTE channel if the output pin was using one.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for setting a GPIOTE output pin.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for clearing a GPIOTE output pin.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for toggling a GPIOTE output pin.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for enabling a GPIOTE output pin task.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for disabling a GPIOTE output pin task.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for getting the address of a configurable GPIOTE task.
+ *
+ * @param[in] pin Pin.
+ *
+ * @return Address of OUT task.
+ */
+uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin);
+
+#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for getting the address of a configurable GPIOTE task.
+ *
+ * @param[in] pin Pin.
+ *
+ * @return Address of SET task.
+ */
+uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin);
+#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for getting the address of a configurable GPIOTE task.
+ *
+ * @param[in] pin Pin.
+ *
+ * @return Address of CLR task.
+ */
+uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin);
+#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+/**
+ * @brief Function for initializing a GPIOTE input pin.
+ * @details The input pin can act in two ways:
+ * - lower accuracy but low power (high frequency clock not needed)
+ * - higher accuracy (high frequency clock required)
+ *
+ * The initial configuration specifies which mode is used.
+ * If high-accuracy mode is used, the driver attempts to allocate one
+ * of the available GPIOTE channels. If no channel is
+ * available, an error is returned.
+ * In low accuracy mode SENSE feature is used. In this case only one active pin
+ * can be detected at a time. It can be worked around by setting all of the used
+ * low accuracy pins to toggle mode.
+ * For more information about SENSE functionality, refer to Product Specification.
+ *
+ * @param[in] pin Pin.
+ * @param[in] p_config Initial configuration.
+ * @param[in] evt_handler User function to be called when the configured transition occurs.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used.
+ * @retval NRFX_ERROR_NO_MEM If no GPIOTE channel is available.
+ */
+nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
+ nrfx_gpiote_in_config_t const * p_config,
+ nrfx_gpiote_evt_handler_t evt_handler);
+
+/**
+ * @brief Function for uninitializing a GPIOTE input pin.
+ * @details The driver frees the GPIOTE channel if the input pin was using one.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for enabling sensing of a GPIOTE input pin.
+ *
+ * @details If the input pin is configured as high-accuracy pin, the function
+ * enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism.
+ * Note that a PORT event is shared between multiple pins, therefore the
+ * interrupt is always enabled.
+ *
+ * @param[in] pin Pin.
+ * @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin.
+ */
+void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable);
+
+/**
+ * @brief Function for disabling a GPIOTE input pin.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for checking if a GPIOTE input pin is set.
+ *
+ * @param[in] pin Pin.
+ *
+ * @retval true If the input pin is set.
+ * @retval false If the input pin is not set.
+ */
+bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for getting the address of a GPIOTE input pin event.
+ * @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned.
+ *
+ * @param[in] pin Pin.
+ */
+uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin);
+
+/**
+ * @brief Function for forcing a specific state on the pin configured as task.
+ *
+ * @param[in] pin Pin.
+ * @param[in] state Pin state.
+ */
+void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state);
+
+/**
+ * @brief Function for triggering the task OUT manually.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin);
+
+#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for triggering the task SET manually.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin);
+#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for triggering the task CLR manually.
+ *
+ * @param[in] pin Pin.
+ */
+void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin);
+#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+
+void nrfx_gpiote_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_GPIOTE_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_i2s.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_i2s.h
new file mode 100644
index 0000000..f64fa21
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_i2s.h
@@ -0,0 +1,254 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_I2S_H__
+#define NRFX_I2S_H__
+
+#include <nrfx.h>
+#include <hal/nrf_i2s.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_i2s I2S driver
+ * @{
+ * @ingroup nrf_i2s
+ * @brief Inter-IC Sound (I2S) peripheral driver.
+ */
+
+
+/**
+ * @brief This value can be provided instead of a pin number for the signals
+ * SDOUT, SDIN, and MCK to specify that a given signal is not used
+ * and therefore does not need to be connected to a pin.
+ */
+#define NRFX_I2S_PIN_NOT_USED 0xFF
+
+/** @brief I2S driver configuration structure. */
+typedef struct
+{
+ uint8_t sck_pin; ///< SCK pin number.
+ uint8_t lrck_pin; ///< LRCK pin number.
+ uint8_t mck_pin; ///< MCK pin number.
+ /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t sdout_pin; ///< SDOUT pin number.
+ /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t sdin_pin; ///< SDIN pin number.
+ /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t irq_priority; ///< Interrupt priority.
+
+ nrf_i2s_mode_t mode; ///< Mode of operation.
+ nrf_i2s_format_t format; ///< Frame format.
+ nrf_i2s_align_t alignment; ///< Alignment of sample within a frame.
+ nrf_i2s_swidth_t sample_width; ///< Sample width.
+ nrf_i2s_channels_t channels; ///< Enabled channels.
+ nrf_i2s_mck_t mck_setup; ///< Master clock setup.
+ nrf_i2s_ratio_t ratio; ///< MCK/LRCK ratio.
+} nrfx_i2s_config_t;
+
+/** @brief I2S driver buffers structure. */
+typedef struct
+{
+ uint32_t * p_rx_buffer;
+ uint32_t const * p_tx_buffer;
+} nrfx_i2s_buffers_t;
+
+/**
+ * @brief I2S driver default configuration.
+ */
+#define NRFX_I2S_DEFAULT_CONFIG \
+{ \
+ .sck_pin = NRFX_I2S_CONFIG_SCK_PIN, \
+ .lrck_pin = NRFX_I2S_CONFIG_LRCK_PIN, \
+ .mck_pin = NRFX_I2S_CONFIG_MCK_PIN, \
+ .sdout_pin = NRFX_I2S_CONFIG_SDOUT_PIN, \
+ .sdin_pin = NRFX_I2S_CONFIG_SDIN_PIN, \
+ .irq_priority = NRFX_I2S_CONFIG_IRQ_PRIORITY, \
+ .mode = (nrf_i2s_mode_t)NRFX_I2S_CONFIG_MASTER, \
+ .format = (nrf_i2s_format_t)NRFX_I2S_CONFIG_FORMAT, \
+ .alignment = (nrf_i2s_align_t)NRFX_I2S_CONFIG_ALIGN, \
+ .sample_width = (nrf_i2s_swidth_t)NRFX_I2S_CONFIG_SWIDTH, \
+ .channels = (nrf_i2s_channels_t)NRFX_I2S_CONFIG_CHANNELS, \
+ .mck_setup = (nrf_i2s_mck_t)NRFX_I2S_CONFIG_MCK_SETUP, \
+ .ratio = (nrf_i2s_ratio_t)NRFX_I2S_CONFIG_RATIO, \
+}
+
+
+#define NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED (1UL << 0)
+ /**< The application should provide buffers that are to be used in the next
+ * part of the transfer. A call to @ref nrfx_i2s_next_buffers_set should
+ * be done before the currently used buffers are completely processed
+ * (i.e. the time remaining for supplying the next buffers depends on
+ * the used size of the buffers). */
+
+/**
+ * @brief I2S driver data handler type.
+ *
+ * A data handling function of this type must be specified during initialization
+ * of the driver. The driver will call this function when it finishes using
+ * buffers passed to it by the application, and when it needs to be provided
+ * with buffers for the next part of the transfer.
+ *
+ * @note The @c p_released pointer passed to this function is temporary and
+ * will be invalid after the function returns, hence it cannot be stored
+ * and used later. If needed, the pointed content (i.e. buffers pointers)
+ * should be copied instead.
+ *
+ * @param[in] p_released Pointer to a structure with pointers to buffers
+ * passed previously to the driver that will no longer
+ * be access by it (they can be now safely released or
+ * used for another purpose, in particular for a next
+ * part of the transfer).
+ * This pointer will be NULL if the application did not
+ * supply the buffers for the next part of the transfer
+ * (via a call to @ref nrfx_i2s_next_buffers_set) since
+ * the previous time the data handler signaled such need.
+ * This means that data corruption occurred (the previous
+ * buffers are used for the second time) and no buffers
+ * can be released at the moment.
+ * Both pointers in this structure are NULL when the
+ * handler is called for the first time after a transfer
+ * is started, because no data has been transferred yet
+ * at this point. In all successive calls the pointers
+ * specify what has been sent (TX) and what has been
+ * received (RX) in the part of transfer that has just
+ * been completed (provided that a given direction is
+ * enabled, see @ref nrfx_i2s_start).
+ * @param[in] status Bit field describing the current status of the transfer.
+ * It can be 0 or a combination of the following flags:
+ * - @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED
+ */
+typedef void (* nrfx_i2s_data_handler_t)(nrfx_i2s_buffers_t const * p_released,
+ uint32_t status);
+
+
+/**
+ * @brief Function for initializing the I2S driver.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] handler Data handler provided by the user. Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ * @retval NRFX_ERROR_INVALID_PARAM If the requested combination of configuration
+ * options is not allowed by the I2S peripheral.
+ */
+nrfx_err_t nrfx_i2s_init(nrfx_i2s_config_t const * p_config,
+ nrfx_i2s_data_handler_t handler);
+
+/** @brief Function for uninitializing the I2S driver. */
+void nrfx_i2s_uninit(void);
+
+/**
+ * @brief Function for starting the continuous I2S transfer.
+ *
+ * The I2S data transfer can be performed in one of three modes: RX (reception)
+ * only, TX (transmission) only, or in both directions simultaneously.
+ * The mode is selected by specifying a proper buffer for a given direction
+ * in the call to this function or by passing NULL instead if this direction
+ * should be disabled.
+ *
+ * The length of the buffer (which is a common value for RX and TX if both
+ * directions are enabled) is specified in 32-bit words. One 32-bit memory
+ * word can either contain four 8-bit samples, two 16-bit samples, or one
+ * right-aligned 24-bit sample sign-extended to a 32-bit value.
+ * For a detailed memory mapping for different supported configurations,
+ * see the @linkProductSpecification52.
+ *
+ * @note Peripherals using EasyDMA (including I2S) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_initial_buffers Pointer to a structure specifying the buffers
+ * to be used in the initial part of the transfer
+ * (buffers for all consecutive parts are provided
+ * through the data handler).
+ * @param[in] buffer_size Size of the buffers (in 32-bit words).
+ * Must not be 0.
+ * @param[in] flags Transfer options (0 for default settings).
+ * Currently, no additional flags are available.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If a transfer was already started or
+ * the driver has not been initialized.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed
+ * in the Data RAM region.
+ */
+nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers,
+ uint16_t buffer_size,
+ uint8_t flags);
+
+/**
+ * @brief Function for supplying the buffers to be used in the next part of
+ * the transfer.
+ *
+ * The application should call this function when the data handler receives
+ * @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED in the @c status parameter.
+ * The call can be done immediately from the data handler function or later,
+ * but it has to be done before the I2S peripheral finishes processing the
+ * buffers supplied previously. Otherwise, data corruption will occur.
+ *
+ * @sa nrfx_i2s_data_handler_t
+ *
+ * @retval NRFX_SUCCESS If the operation was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the buffers were already supplied or
+ * the peripheral is currently being stopped.
+ */
+nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers);
+
+/** @brief Function for stopping the I2S transfer. */
+void nrfx_i2s_stop(void);
+
+/** @} */
+
+
+void nrfx_i2s_irq_handler(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_I2S_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_lpcomp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_lpcomp.h
new file mode 100644
index 0000000..f6744a3
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_lpcomp.h
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_LPCOMP_H__
+#define NRFX_LPCOMP_H__
+
+#include <nrfx.h>
+#include <hal/nrf_lpcomp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_lpcomp LPCOMP driver
+ * @{
+ * @ingroup nrf_lpcomp
+ * @brief Low Power Comparator (LPCOMP) peripheral driver.
+ */
+
+/**
+ * @brief LPCOMP event handler function type.
+ * @param[in] event LPCOMP event.
+ */
+typedef void (* nrfx_lpcomp_event_handler_t)(nrf_lpcomp_event_t event);
+
+/** @brief LPCOMP configuration. */
+typedef struct
+{
+ nrf_lpcomp_config_t hal; /**< LPCOMP HAL configuration. */
+ nrf_lpcomp_input_t input; /**< Input to be monitored. */
+ uint8_t interrupt_priority; /**< LPCOMP interrupt priority. */
+} nrfx_lpcomp_config_t;
+
+/** @brief LPCOMP driver default configuration including the LPCOMP HAL configuration. */
+#ifdef NRF52_SERIES
+#define NRFX_LPCOMP_DEFAULT_CONFIG \
+ { \
+ .hal = { (nrf_lpcomp_ref_t)NRFX_LPCOMP_CONFIG_REFERENCE , \
+ (nrf_lpcomp_detect_t)NRFX_LPCOMP_CONFIG_DETECTION, \
+ (nrf_lpcomp_hysteresis_t)NRFX_LPCOMP_CONFIG_HYST }, \
+ .input = (nrf_lpcomp_input_t)NRFX_LPCOMP_CONFIG_INPUT, \
+ .interrupt_priority = NRFX_LPCOMP_CONFIG_IRQ_PRIORITY \
+ }
+#else
+#define NRFX_LPCOMP_DEFAULT_CONFIG \
+ { \
+ .hal = { (nrf_lpcomp_ref_t)NRFX_LPCOMP_CONFIG_REFERENCE , \
+ (nrf_lpcomp_detect_t)NRFX_LPCOMP_CONFIG_DETECTION }, \
+ .input = (nrf_lpcomp_input_t)NRFX_LPCOMP_CONFIG_INPUT, \
+ .interrupt_priority = NRFX_LPCOMP_CONFIG_IRQ_PRIORITY \
+ }
+#endif
+
+/**
+ * @brief Function for initializing the LPCOMP driver.
+ *
+ * This function initializes the LPCOMP driver, but does not enable the peripheral or any interrupts.
+ * To start the driver, call the function nrfx_lpcomp_enable() after initialization.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver has already been initialized.
+ * @retval NRFX_ERROR_BUSY If the COMP peripheral is already in use.
+ * This is possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,
+ nrfx_lpcomp_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the LCOMP driver.
+ *
+ * This function uninitializes the LPCOMP driver. The LPCOMP peripheral and
+ * its interrupts are disabled, and local variables are cleaned. After this call, you must
+ * initialize the driver again by calling nrfx_lpcomp_init() if you want to use it.
+ *
+ * @sa nrfx_lpcomp_disable()
+ * @sa nrfx_lpcomp_init()
+ */
+void nrfx_lpcomp_uninit(void);
+
+/**@brief Function for enabling the LPCOMP peripheral and interrupts.
+ *
+ * Before calling this function, the driver must be initialized. This function
+ * enables the LPCOMP peripheral and its interrupts.
+ *
+ * @sa nrfx_lpcomp_disable()
+ */
+void nrfx_lpcomp_enable(void);
+
+/**@brief Function for disabling the LPCOMP peripheral.
+ *
+ * Before calling this function, the driver must be initialized. This function disables the LPCOMP
+ * peripheral and its interrupts.
+ *
+ * @sa nrfx_lpcomp_enable()
+ */
+void nrfx_lpcomp_disable(void);
+
+
+void nrfx_lpcomp_irq_handler(void);
+
+/** @} **/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_LPCOMP_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pdm.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pdm.h
new file mode 100644
index 0000000..f2201c9
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pdm.h
@@ -0,0 +1,214 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_PDM_H__
+#define NRFX_PDM_H__
+
+#include <nrfx.h>
+#include <hal/nrf_pdm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_pdm PDM driver
+ * @{
+ * @ingroup nrf_pdm
+ * @brief Pulse Density Modulation (PDM) peripheral driver.
+ */
+
+
+#define NRFX_PDM_MAX_BUFFER_SIZE 32767
+
+
+/**
+ * @brief PDM error type.
+ */
+typedef enum
+{
+ NRFX_PDM_NO_ERROR = 0,
+ NRFX_PDM_ERROR_OVERFLOW = 1
+} nrfx_pdm_error_t;
+
+/**
+ * @brief PDM event structure.
+ */
+typedef struct
+{
+ bool buffer_requested; ///< Buffer request flag.
+ int16_t * buffer_released; ///< Pointer to the released buffer. Can be NULL.
+ nrfx_pdm_error_t error; ///< Error type.
+} nrfx_pdm_evt_t;
+
+/**
+ * @brief PDM interface driver configuration structure.
+ */
+typedef struct
+{
+ nrf_pdm_mode_t mode; ///< Interface operation mode.
+ nrf_pdm_edge_t edge; ///< Sampling mode.
+ uint8_t pin_clk; ///< CLK pin.
+ uint8_t pin_din; ///< DIN pin.
+ nrf_pdm_freq_t clock_freq; ///< Clock frequency.
+ nrf_pdm_gain_t gain_l; ///< Left channel gain.
+ nrf_pdm_gain_t gain_r; ///< Right channel gain.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+} nrfx_pdm_config_t;
+
+/**
+ * @brief Macro for setting @ref nrfx_pdm_config_t to default settings
+ * in single ended mode.
+ *
+ * @param _pin_clk CLK output pin.
+ * @param _pin_din DIN input pin.
+ */
+#define NRFX_PDM_DEFAULT_CONFIG(_pin_clk, _pin_din) \
+{ \
+ .mode = (nrf_pdm_mode_t)NRFX_PDM_CONFIG_MODE, \
+ .edge = (nrf_pdm_edge_t)NRFX_PDM_CONFIG_EDGE, \
+ .pin_clk = _pin_clk, \
+ .pin_din = _pin_din, \
+ .clock_freq = (nrf_pdm_freq_t)NRFX_PDM_CONFIG_CLOCK_FREQ, \
+ .gain_l = NRF_PDM_GAIN_DEFAULT, \
+ .gain_r = NRF_PDM_GAIN_DEFAULT, \
+ .interrupt_priority = NRFX_PDM_CONFIG_IRQ_PRIORITY \
+}
+
+/**
+ * @brief Handler for PDM interface ready events.
+ *
+ * This event handler is called on a buffer request, an error or when a buffer
+ * is full and ready to be processed.
+ *
+ * @param[in] p_evt Pointer to the PDM event structure.
+ */
+typedef void (*nrfx_pdm_event_handler_t)(nrfx_pdm_evt_t const * const p_evt);
+
+
+/**
+ * @brief Function for initializing the PDM interface.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user. Cannot be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is already initialized.
+ * @retval NRFX_ERROR_INVALID_PARAM If invalid configuration was specified.
+ */
+nrfx_err_t nrfx_pdm_init(nrfx_pdm_config_t const * p_config,
+ nrfx_pdm_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the PDM interface.
+ *
+ * This function stops PDM sampling, if it is in progress.
+ */
+void nrfx_pdm_uninit(void);
+
+/**
+ * @brief Function for getting the address of a PDM interface task.
+ *
+ * @param[in] task Task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_pdm_task_address_get(nrf_pdm_task_t task)
+{
+ return nrf_pdm_task_address_get(task);
+}
+
+/**
+ * @brief Function for getting the state of the PDM interface.
+ *
+ * @retval true If the PDM interface is enabled.
+ * @retval false If the PDM interface is disabled.
+ */
+__STATIC_INLINE bool nrfx_pdm_enable_check(void)
+{
+ return nrf_pdm_enable_check();
+}
+
+/**
+ * @brief Function for starting PDM sampling.
+ *
+ * @retval NRFX_SUCCESS If sampling was started successfully or was already in progress.
+ * @retval NRFX_ERROR_BUSY If a previous start/stop operation is in progress.
+ */
+nrfx_err_t nrfx_pdm_start(void);
+
+/**
+ * @brief Function for stopping PDM sampling.
+ *
+ * When this function is called, the PDM interface is stopped after finishing
+ * the current frame.
+ * The event handler function might be called once more after calling this function.
+ *
+ * @retval NRFX_SUCCESS If sampling was stopped successfully or was already stopped before.
+ * @retval NRFX_ERROR_BUSY If a previous start/stop operation is in progress.
+ */
+nrfx_err_t nrfx_pdm_stop(void);
+
+/**
+ * @brief Function for supplying the sample buffer.
+ *
+ * Call this function after every buffer request event.
+ *
+ * @param[in] buffer Pointer to the receive buffer. Cannot be NULL.
+ * @param[in] buffer_length Length of the receive buffer in 16-bit words.
+ *
+ * @retval NRFX_SUCCESS If the buffer was applied successfully.
+ * @retval NRFX_ERROR_BUSY If the buffer was already supplied or the peripheral is currently being stopped.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was not initialized.
+ * @retval NRFX_ERROR_INVALID_PARAM If invalid parameters were provided.
+ */
+nrfx_err_t nrfx_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length);
+
+
+void nrfx_pdm_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_PDM_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power.h
new file mode 100644
index 0000000..c7bac84
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power.h
@@ -0,0 +1,382 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_POWER_H__
+#define NRFX_POWER_H__
+
+#include <nrfx.h>
+#include <hal/nrf_power.h>
+#include <nrfx_power_clock.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_power POWER driver
+ * @{
+ * @ingroup nrf_power
+ * @brief POWER peripheral driver.
+ */
+
+/**
+ * @brief Power mode possible configurations
+ */
+typedef enum
+{
+ NRFX_POWER_MODE_CONSTLAT, /**< Constant latency mode */
+ NRFX_POWER_MODE_LOWPWR /**< Low power mode */
+}nrfx_power_mode_t;
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Events from power system
+ */
+typedef enum
+{
+ NRFX_POWER_SLEEP_EVT_ENTER, /**< CPU entered WFI/WFE sleep
+ *
+ * Keep in mind that if this interrupt is enabled,
+ * it means that CPU was waken up just after WFI by this interrupt.
+ */
+ NRFX_POWER_SLEEP_EVT_EXIT /**< CPU exited WFI/WFE sleep */
+}nrfx_power_sleep_evt_t;
+#endif /* NRF_POWER_HAS_SLEEPEVT */
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Events from USB power system
+ */
+typedef enum
+{
+ NRFX_POWER_USB_EVT_DETECTED, /**< USB power detected on the connector (plugged in). */
+ NRFX_POWER_USB_EVT_REMOVED, /**< USB power removed from the connector. */
+ NRFX_POWER_USB_EVT_READY /**< USB power regulator ready. */
+}nrfx_power_usb_evt_t;
+
+/**
+ * @brief USB power state
+ *
+ * The single enumerator that holds all data about current state of USB
+ * related POWER.
+ *
+ * Organized this way that higher power state has higher numeric value
+ */
+typedef enum
+{
+ NRFX_POWER_USB_STATE_DISCONNECTED, /**< No power on USB lines detected */
+ NRFX_POWER_USB_STATE_CONNECTED, /**< The USB power is detected, but USB power regulator is not ready */
+ NRFX_POWER_USB_STATE_READY /**< From the power point of view USB is ready for working */
+}nrfx_power_usb_state_t;
+#endif /* NRF_POWER_HAS_USBREG */
+
+/**
+ * @name Callback types
+ *
+ * Defined types of callback functions
+ * @{
+ */
+/**
+ * @brief Event handler for power failure warning
+ */
+typedef void (*nrfx_power_pofwarn_event_handler_t)(void);
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Event handler for entering/exiting sleep
+ *
+ * @param event Event type
+ */
+typedef void (*nrfx_power_sleep_event_handler_t)(nrfx_power_sleep_evt_t event);
+#endif
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Event handler for USB related power events
+ *
+ * @param event Event type
+ */
+typedef void (*nrfx_power_usb_event_handler_t)(nrfx_power_usb_evt_t event);
+#endif
+/** @} */
+
+/**
+ * @brief General power configuration
+ *
+ * Parameters required to initialize power driver.
+ */
+typedef struct
+{
+ /**
+ * @brief Enable main DCDC regulator
+ *
+ * This bit only informs the driver that elements for DCDC regulator
+ * are installed and regulator can be used.
+ * The regulator would be enabled or disabled automatically
+ * by the hardware, basing on current power requirement.
+ */
+ bool dcdcen:1;
+
+#if NRF_POWER_HAS_VDDH || defined(__NRFX_DOXYGEN__)
+ /**
+ * @brief Enable HV DCDC regulator
+ *
+ * This bit only informs the driver that elements for DCDC regulator
+ * are installed and regulator can be used.
+ * The regulator would be enabled or disabled automatically
+ * by the hardware, basing on current power requirement.
+ */
+ bool dcdcenhv: 1;
+#endif
+}nrfx_power_config_t;
+
+/**
+ * @brief The configuration for power failure comparator
+ *
+ * Configuration used to enable and configure power failure comparator
+ */
+typedef struct
+{
+ nrfx_power_pofwarn_event_handler_t handler; //!< Event handler
+ nrf_power_pof_thr_t thr; //!< Threshold for power failure detection
+#if NRF_POWER_HAS_VDDH || defined(__NRFX_DOXYGEN__)
+ nrf_power_pof_thrvddh_t thrvddh; //!< Threshold for power failure detection on VDDH pin
+#endif
+}nrfx_power_pofwarn_config_t;
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief The configuration of sleep event processing
+ *
+ * Configuration used to enable and configure sleep event handling
+ */
+typedef struct
+{
+ nrfx_power_sleep_event_handler_t handler; //!< Event handler
+ bool en_enter:1; //!< Enable event on sleep entering
+ bool en_exit :1; //!< Enable event on sleep exiting
+}nrfx_power_sleepevt_config_t;
+#endif
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief The configuration of USB related power events
+ *
+ * Configuration used to enable and configure USB power event handling
+ */
+typedef struct
+{
+ nrfx_power_usb_event_handler_t handler; //!< Event processing
+}nrfx_power_usbevt_config_t;
+#endif /* NRF_POWER_HAS_USBREG */
+
+/**
+ * @brief Function for getting the handler of the power failure comparator.
+ * @return Handler of the power failure comparator.
+ */
+nrfx_power_pofwarn_event_handler_t nrfx_power_pof_handler_get(void);
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for getting the handler of the USB power.
+ * @return Handler of the USB power.
+ */
+nrfx_power_usb_event_handler_t nrfx_power_usb_handler_get(void);
+#endif
+
+/**
+ * @brief Initialize power module driver
+ *
+ * Enabled power module driver would process all the interrupts from power system.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ *
+ * @retval NRFX_SUCCESS Successfully initialized.
+ * @retval NRFX_ERROR_ALREADY_INITIALIZED Module was already initialized.
+ */
+nrfx_err_t nrfx_power_init(nrfx_power_config_t const * p_config);
+
+/**
+ * @brief Unintialize power module driver
+ *
+ * Disables all the interrupt handling in the module.
+ *
+ * @sa nrfx_power_init
+ */
+void nrfx_power_uninit(void);
+
+/**
+ * @brief Initialize power failure comparator
+ *
+ * Configures the power failure comparator. This function does not setup and enable it.
+ * Those steps can be done with functions @ref nrfx_power_pof_enable and @ref nrfx_power_pof_disable
+ * or with Softdevice API (when Softdevice is using).
+ *
+ * @param[in] p_config Configuration with values and event handler.
+ * If event handler is set to NULL, interrupt would be disabled.
+ */
+void nrfx_power_pof_init(nrfx_power_pofwarn_config_t const * p_config);
+
+/**
+ * @brief Enable power failure comparator
+ * Sets and enables interrupt of the power failure comparator. This functions cannot be using
+ * when Softdevice is enabled. If event handler set in init function is set to NULL, interrupt
+ * would be disabled.
+ *
+ * @param[in] p_config Configuration with values and event handler.
+ */
+void nrfx_power_pof_enable(nrfx_power_pofwarn_config_t const * p_config);
+
+/**
+ * @brief Disable the power failure comparator
+ *
+ * Disables the power failure comparator interrupt.
+ */
+void nrfx_power_pof_disable(void);
+
+/**
+ * @brief Clear the power failure comparator settings
+ *
+ * Clears the settings of the power failure comparator.
+ */
+void nrfx_power_pof_uninit(void);
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Initialize sleep entering and exiting events processing
+ *
+ * Configures and setups the sleep event processing.
+ *
+ * @param[in] p_config Configuration with values and event handler.
+ *
+ * @sa nrfx_power_sleepevt_uninit
+ *
+ */
+void nrfx_power_sleepevt_init(nrfx_power_sleepevt_config_t const * p_config);
+
+/**
+ * @brief Enable sleep entering and exiting events processing
+ *
+ * @param[in] p_config Configuration with values and event handler.
+ */
+void nrfx_power_sleepevt_enable(nrfx_power_sleepevt_config_t const * p_config);
+
+/**
+ * @brief Disable sleep entering and exiting events processing
+ */
+void nrfx_power_sleepevt_disable(void);
+
+/**
+ * @brief Uninitialize sleep entering and exiting events processing
+ *
+ * @sa nrfx_power_sleepevt_init
+ */
+void nrfx_power_sleepevt_uninit(void);
+#endif /* NRF_POWER_HAS_SLEEPEVT */
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Initialize USB power event processing
+ *
+ * Configures and setups the USB power event processing.
+ *
+ * @param[in] p_config Configuration with values and event handler.
+ *
+ * @sa nrfx_power_usbevt_uninit
+ */
+void nrfx_power_usbevt_init(nrfx_power_usbevt_config_t const * p_config);
+
+/**
+ * @brief Enable USB power event processing
+ */
+void nrfx_power_usbevt_enable(void);
+
+/**
+ * @brief Disable USB power event processing
+ */
+void nrfx_power_usbevt_disable(void);
+
+/**
+ * @brief Uninitalize USB power event processing
+ *
+ * @sa nrfx_power_usbevt_init
+ */
+void nrfx_power_usbevt_uninit(void);
+
+/**
+ * @brief Get the status of USB power
+ *
+ * @return Current USB power status
+ */
+__STATIC_INLINE nrfx_power_usb_state_t nrfx_power_usbstatus_get(void);
+
+#endif /* NRF_POWER_HAS_USBREG */
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+#if NRF_POWER_HAS_USBREG
+__STATIC_INLINE nrfx_power_usb_state_t nrfx_power_usbstatus_get(void)
+{
+ uint32_t status = nrf_power_usbregstatus_get();
+ if(0 == (status & NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK))
+ {
+ return NRFX_POWER_USB_STATE_DISCONNECTED;
+ }
+ if(0 == (status & NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK))
+ {
+ return NRFX_POWER_USB_STATE_CONNECTED;
+ }
+ return NRFX_POWER_USB_STATE_READY;
+}
+#endif /* NRF_POWER_HAS_USBREG */
+
+#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
+
+
+void nrfx_power_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRFX_POWER_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power_clock.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power_clock.h
new file mode 100644
index 0000000..c63dbcf
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_power_clock.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_POWER_CLOCK_H__
+#define NRFX_POWER_CLOCK_H__
+
+#include <nrfx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+__STATIC_INLINE void nrfx_power_clock_irq_init(void);
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+__STATIC_INLINE void nrfx_power_clock_irq_init(void)
+{
+ uint8_t priority;
+#if NRFX_CHECK(NRFX_POWER_ENABLED) && NRFX_CHECK(NRFX_CLOCK_ENABLED)
+ #if NRFX_POWER_CONFIG_IRQ_PRIORITY != NRFX_CLOCK_CONFIG_IRQ_PRIORITY
+ #error "IRQ priority for POWER and CLOCK have to be the same. Check <nrfx_config.h>."
+ #endif
+ priority = NRFX_POWER_CONFIG_IRQ_PRIORITY;
+#elif NRFX_CHECK(NRFX_POWER_ENABLED)
+ priority = NRFX_POWER_CONFIG_IRQ_PRIORITY;
+#elif NRFX_CHECK(NRFX_CLOCK_ENABLED)
+ priority = NRFX_CLOCK_CONFIG_IRQ_PRIORITY;
+#endif
+
+ if (!NRFX_IRQ_IS_ENABLED(POWER_CLOCK_IRQn))
+ {
+ NRFX_IRQ_PRIORITY_SET(POWER_CLOCK_IRQn, priority);
+ NRFX_IRQ_ENABLE(POWER_CLOCK_IRQn);
+ }
+}
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+#if NRFX_CHECK(NRFX_POWER_ENABLED) && NRFX_CHECK(NRFX_CLOCK_ENABLED)
+void nrfx_power_clock_irq_handler(void);
+#elif NRFX_CHECK(NRFX_POWER_ENABLED)
+#define nrfx_power_irq_handler nrfx_power_clock_irq_handler
+#elif NRFX_CHECK(NRFX_CLOCK_ENABLED)
+#define nrfx_clock_irq_handler nrfx_power_clock_irq_handler
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_POWER_CLOCK_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_ppi.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_ppi.h
new file mode 100644
index 0000000..f7b9b24
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_ppi.h
@@ -0,0 +1,327 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_PPI_H__
+#define NRFX_PPI_H__
+
+#include <nrfx.h>
+#include <hal/nrf_ppi.h>
+
+/**
+ * @defgroup nrfx_ppi PPI allocator
+ * @{
+ * @ingroup nrf_ppi
+ * @brief Programmable Peripheral Interconnect (PPI) allocator.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NRFX_PPI_CHANNELS_USED
+#define NRFX_PPI_CHANNELS_USED 0
+#endif
+
+#ifndef NRFX_PPI_GROUPS_USED
+#define NRFX_PPI_GROUPS_USED 0
+#endif
+
+#if PPI_CH_NUM > 16
+#define NRFX_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFFFFFFFuL & ~(NRFX_PPI_CHANNELS_USED)) /**< All PPI channels available to the application. */
+#define NRFX_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x000FFFFFuL & ~(NRFX_PPI_CHANNELS_USED)) /**< Programmable PPI channels available to the application. */
+#else
+#define NRFX_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFF0FFFFuL & ~(NRFX_PPI_CHANNELS_USED)) /**< All PPI channels available to the application. */
+#define NRFX_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x0000FFFFuL & ~(NRFX_PPI_CHANNELS_USED)) /**< Programmable PPI channels available to the application. */
+#endif
+
+#define NRFX_PPI_ALL_APP_GROUPS_MASK (((1uL << PPI_GROUP_NUM) - 1) & ~(NRFX_PPI_GROUPS_USED)) /**< All PPI groups available to the application. */
+
+/**
+ * @brief Function for uninitializing the PPI module.
+ *
+ * This function disables all channels and clears the channel groups.
+ */
+void nrfx_ppi_free_all(void);
+
+/**
+ * @brief Function for allocating a PPI channel.
+ * @details This function allocates the first unused PPI channel.
+ *
+ * @param[out] p_channel Pointer to the PPI channel that has been allocated.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully allocated.
+ * @retval NRFX_ERROR_NO_MEM If there is no available channel to be used.
+ */
+nrfx_err_t nrfx_ppi_channel_alloc(nrf_ppi_channel_t * p_channel);
+
+/**
+ * @brief Function for freeing a PPI channel.
+ * @details This function also disables the chosen channel.
+ *
+ * @param[in] channel PPI channel to be freed.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully freed.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel is not user-configurable.
+ */
+nrfx_err_t nrfx_ppi_channel_free(nrf_ppi_channel_t channel);
+
+/**
+ * @brief Function for assigning task and event endpoints to the PPI channel.
+ *
+ * @param[in] channel PPI channel to be assigned endpoints.
+ * @param[in] eep Event endpoint address.
+ * @param[in] tep Task endpoint address.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully assigned.
+ * @retval NRFX_ERROR_INVALID_STATE If the channel is not allocated for the user.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel is not user-configurable.
+ */
+nrfx_err_t nrfx_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep);
+
+/**
+ * @brief Function for assigning or clearing fork endpoint to the PPI channel.
+ *
+ * @param[in] channel PPI channel to be assigned endpoints.
+ * @param[in] fork_tep Fork task endpoint address or 0 to clear.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully assigned.
+ * @retval NRFX_ERROR_INVALID_STATE If the channel is not allocated for the user.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel is not user-configurable.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If function is not supported.
+ */
+nrfx_err_t nrfx_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep);
+
+/**
+ * @brief Function for enabling a PPI channel.
+ *
+ * @param[in] channel PPI channel to be enabled.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully enabled.
+ * @retval NRFX_ERROR_INVALID_STATE If the user-configurable channel is not allocated.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel cannot be enabled by the user.
+ */
+nrfx_err_t nrfx_ppi_channel_enable(nrf_ppi_channel_t channel);
+
+/**
+ * @brief Function for disabling a PPI channel.
+ *
+ * @param[in] channel PPI channel to be disabled.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully disabled.
+ * @retval NRFX_ERROR_INVALID_STATE If the user-configurable channel is not allocated.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel cannot be disabled by the user.
+ */
+nrfx_err_t nrfx_ppi_channel_disable(nrf_ppi_channel_t channel);
+
+/**
+ * @brief Function for allocating a PPI channel group.
+ * @details This function allocates the first unused PPI group.
+ *
+ * @param[out] p_group Pointer to the PPI channel group that has been allocated.
+ *
+ * @retval NRFX_SUCCESS If the channel group was successfully allocated.
+ * @retval NRFX_ERROR_NO_MEM If there is no available channel group to be used.
+ */
+nrfx_err_t nrfx_ppi_group_alloc(nrf_ppi_channel_group_t * p_group);
+
+/**
+ * @brief Function for freeing a PPI channel group.
+ * @details This function also disables the chosen group.
+ *
+ * @param[in] group PPI channel group to be freed.
+ *
+ * @retval NRFX_SUCCESS If the channel group was successfully freed.
+ * @retval NRFX_ERROR_INVALID_PARAM If the channel group is not user-configurable.
+ */
+nrfx_err_t nrfx_ppi_group_free(nrf_ppi_channel_group_t group);
+
+/**
+ * @brief Compute a channel mask for NRF_PPI registers.
+ *
+ * @param[in] channel Channel number to transform to a mask.
+ *
+ * @retval Channel mask.
+ */
+__STATIC_INLINE uint32_t nrfx_ppi_channel_to_mask(nrf_ppi_channel_t channel)
+{
+ return (1uL << (uint32_t) channel);
+}
+
+/**
+ * @brief Function for including multiple PPI channels in a channel group.
+ *
+ * @param[in] channel_mask PPI channels to be added.
+ * @param[in] group Channel group in which to include the channels.
+ *
+ * @retval NRFX_SUCCESS If the channels was successfully included.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group or channels are not an
+ * application channels.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+nrfx_err_t nrfx_ppi_channels_include_in_group(uint32_t channel_mask,
+ nrf_ppi_channel_group_t group);
+
+/**
+ * @brief Function for including a PPI channel in a channel group.
+ *
+ * @param[in] channel PPI channel to be added.
+ * @param[in] group Channel group in which to include the channel.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully included.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group or channel is not an
+ * application channel.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+__STATIC_INLINE nrfx_err_t nrfx_ppi_channel_include_in_group(nrf_ppi_channel_t channel,
+ nrf_ppi_channel_group_t group)
+{
+ return nrfx_ppi_channels_include_in_group(nrfx_ppi_channel_to_mask(channel), group);
+}
+
+/**
+ * @brief Function for removing multiple PPI channels from a channel group.
+ *
+ * @param[in] channel_mask PPI channels to be removed.
+ * @param[in] group Channel group from which to remove the channels.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully removed.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group or channels are not an
+ * application channels.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+nrfx_err_t nrfx_ppi_channels_remove_from_group(uint32_t channel_mask,
+ nrf_ppi_channel_group_t group);
+
+/**
+ * @brief Function for removing a PPI channel from a channel group.
+ *
+ * @param[in] channel PPI channel to be removed.
+ * @param[in] group Channel group from which to remove the channel.
+ *
+ * @retval NRFX_SUCCESS If the channel was successfully removed.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group or channel is not an
+ * application channel.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+__STATIC_INLINE nrfx_err_t nrfx_ppi_channel_remove_from_group(nrf_ppi_channel_t channel,
+ nrf_ppi_channel_group_t group)
+{
+ return nrfx_ppi_channels_remove_from_group(nrfx_ppi_channel_to_mask(channel), group);
+}
+
+/**
+ * @brief Function for clearing a PPI channel group.
+ *
+ * @param[in] group Channel group to be cleared.
+ *
+ * @retval NRFX_SUCCESS If the group was successfully cleared.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+__STATIC_INLINE nrfx_err_t nrfx_ppi_group_clear(nrf_ppi_channel_group_t group)
+{
+ return nrfx_ppi_channels_remove_from_group(NRFX_PPI_ALL_APP_CHANNELS_MASK, group);
+}
+
+/**
+ * @brief Function for enabling a PPI channel group.
+ *
+ * @param[in] group Channel group to be enabled.
+ *
+ * @retval NRFX_SUCCESS If the group was successfully enabled.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+nrfx_err_t nrfx_ppi_group_enable(nrf_ppi_channel_group_t group);
+
+/**
+ * @brief Function for disabling a PPI channel group.
+ *
+ * @param[in] group Channel group to be disabled.
+ *
+ * @retval NRFX_SUCCESS If the group was successfully disabled.
+ * @retval NRFX_ERROR_INVALID_PARAM If group is not an application group.
+ * @retval NRFX_ERROR_INVALID_STATE If group is not an allocated group.
+ */
+nrfx_err_t nrfx_ppi_group_disable(nrf_ppi_channel_group_t group);
+
+/**
+ * @brief Function for getting the address of a PPI task.
+ *
+ * @param[in] task Task.
+ *
+ * @retval Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_ppi_task_addr_get(nrf_ppi_task_t task)
+{
+ return (uint32_t) nrf_ppi_task_address_get(task);
+}
+
+/**
+ * @brief Function for getting the address of a PPI group enable task.
+ *
+ * @param[in] group PPI channel group
+ *
+ * @retval Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_ppi_task_addr_group_enable_get(nrf_ppi_channel_group_t group)
+{
+ return (uint32_t) nrf_ppi_task_group_enable_address_get(group);
+}
+
+/**
+ * @brief Function for getting the address of a PPI group enable task.
+ *
+ * @param[in] group PPI channel group
+ *
+ * @retval Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_ppi_task_addr_group_disable_get(nrf_ppi_channel_group_t group)
+{
+ return (uint32_t) nrf_ppi_task_group_disable_address_get(group);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_PPI_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pwm.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pwm.h
new file mode 100644
index 0000000..c4c15dd
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_pwm.h
@@ -0,0 +1,497 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_PWM_H__
+#define NRFX_PWM_H__
+
+#include <nrfx.h>
+#include <hal/nrf_pwm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_pwm PWM driver
+ * @{
+ * @ingroup nrf_pwm
+ * @brief Pulse Width Modulation (PWM) peripheral driver.
+ */
+
+/**
+ * @brief PWM driver instance data structure.
+ */
+typedef struct
+{
+ NRF_PWM_Type * p_registers; ///< Pointer to the structure with PWM peripheral instance registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_pwm_t;
+
+/**
+ * @brief Macro for creating a PWM driver instance.
+ */
+#define NRFX_PWM_INSTANCE(id) \
+{ \
+ .p_registers = NRFX_CONCAT_2(NRF_PWM, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_PWM, id, _INST_IDX), \
+}
+
+enum {
+#if NRFX_CHECK(NRFX_PWM0_ENABLED)
+ NRFX_PWM0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_PWM1_ENABLED)
+ NRFX_PWM1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_PWM2_ENABLED)
+ NRFX_PWM2_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_PWM3_ENABLED)
+ NRFX_PWM3_INST_IDX,
+#endif
+ NRFX_PWM_ENABLED_COUNT
+};
+
+/**
+ * @brief This value can be provided instead of a pin number for any channel
+ * to specify that its output is not used and therefore does not need
+ * to be connected to a pin.
+ */
+#define NRFX_PWM_PIN_NOT_USED 0xFF
+
+/**
+ * @brief This value can be added to a pin number to inverse its polarity
+ * (set idle state = 1).
+ */
+#define NRFX_PWM_PIN_INVERTED 0x80
+
+/**
+ * @brief PWM driver configuration structure.
+ */
+typedef struct
+{
+ uint8_t output_pins[NRF_PWM_CHANNEL_COUNT]; ///< Pin numbers for individual output channels (optional).
+ /**< Use @ref NRFX_PWM_PIN_NOT_USED
+ * if a given output channel is not needed. */
+ uint8_t irq_priority; ///< Interrupt priority.
+ nrf_pwm_clk_t base_clock; ///< Base clock frequency.
+ nrf_pwm_mode_t count_mode; ///< Operating mode of the pulse generator counter.
+ uint16_t top_value; ///< Value up to which the pulse generator counter counts.
+ nrf_pwm_dec_load_t load_mode; ///< Mode of loading sequence data from RAM.
+ nrf_pwm_dec_step_t step_mode; ///< Mode of advancing the active sequence.
+} nrfx_pwm_config_t;
+
+/**
+ * @brief PWM driver default configuration.
+ */
+#define NRFX_PWM_DEFAULT_CONFIG \
+{ \
+ .output_pins = { NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN, \
+ NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN, \
+ NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN, \
+ NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN }, \
+ .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .base_clock = (nrf_pwm_clk_t)NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK, \
+ .count_mode = (nrf_pwm_mode_t)NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE, \
+ .top_value = NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE, \
+ .load_mode = (nrf_pwm_dec_load_t)NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE, \
+ .step_mode = (nrf_pwm_dec_step_t)NRFX_PWM_DEFAULT_CONFIG_STEP_MODE, \
+}
+
+
+/**
+ * @brief PWM flags providing additional playback options.
+ */
+typedef enum
+{
+ NRFX_PWM_FLAG_STOP = 0x01, /**< When the requested playback is finished,
+ the peripheral should be stopped.
+ @note The STOP task is triggered when
+ the last value of the final sequence is
+ loaded from RAM, and the peripheral stops
+ at the end of the current PWM period.
+ For sequences with configured repeating
+ of duty cycle values, this might result in
+ less than the requested number of repeats
+ of the last value. */
+ NRFX_PWM_FLAG_LOOP = 0x02, /**< When the requested playback is finished,
+ it should be started from the beginning.
+ This flag is ignored if used together
+ with @ref NRFX_PWM_FLAG_STOP.
+ @note The playback restart is done via a
+ shortcut configured in the PWM peripheral.
+ This shortcut triggers the proper starting
+ task when the final value of previous
+ playback is read from RAM and applied to
+ the pulse generator counter.
+ When this mechanism is used together with
+ the @ref NRF_PWM_STEP_TRIGGERED mode,
+ the playback restart will occur right
+ after switching to the final value (this
+ final value will be played only once). */
+ NRFX_PWM_FLAG_SIGNAL_END_SEQ0 = 0x04, /**< The event handler should be
+ called when the last value
+ from sequence 0 is loaded. */
+ NRFX_PWM_FLAG_SIGNAL_END_SEQ1 = 0x08, /**< The event handler should be
+ called when the last value
+ from sequence 1 is loaded. */
+ NRFX_PWM_FLAG_NO_EVT_FINISHED = 0x10, /**< The playback finished event
+ (enabled by default) should be
+ suppressed. */
+ NRFX_PWM_FLAG_START_VIA_TASK = 0x80, /**< The playback should not be
+ started directly by the called
+ function. Instead, the function
+ should only prepare it and
+ return the address of the task
+ to be triggered to start the
+ playback. */
+} nrfx_pwm_flag_t;
+
+
+/**
+ * @brief PWM driver event type.
+ */
+typedef enum
+{
+ NRFX_PWM_EVT_FINISHED, ///< Sequence playback finished.
+ NRFX_PWM_EVT_END_SEQ0, /**< End of sequence 0 reached. Its data can be
+ safely modified now. */
+ NRFX_PWM_EVT_END_SEQ1, /**< End of sequence 1 reached. Its data can be
+ safely modified now. */
+ NRFX_PWM_EVT_STOPPED, ///< The PWM peripheral has been stopped.
+} nrfx_pwm_evt_type_t;
+
+/**
+ * @brief PWM driver event handler type.
+ */
+typedef void (* nrfx_pwm_handler_t)(nrfx_pwm_evt_type_t event_type);
+
+
+/**
+ * @brief Function for initializing the PWM driver.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ *
+ * @param[in] handler Event handler provided by the user. If NULL is passed
+ * instead, event notifications are not done and PWM
+ * interrupts are disabled.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ */
+nrfx_err_t nrfx_pwm_init(nrfx_pwm_t const * const p_instance,
+ nrfx_pwm_config_t const * p_config,
+ nrfx_pwm_handler_t handler);
+
+/**
+ * @brief Function for uninitializing the PWM driver.
+ *
+ * If any sequence playback is in progress, it is stopped immediately.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_pwm_uninit(nrfx_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for starting a single sequence playback.
+ *
+ * To take advantage of the looping mechanism in the PWM peripheral, both
+ * sequences must be used (single sequence can be played back only once by
+ * the peripheral). Therefore, the provided sequence is internally set and
+ * played back as both sequence 0 and sequence 1. Consequently, if end of
+ * sequence notifications are required, events for both sequences should be
+ * used (that means that both the @ref NRFX_PWM_FLAG_SIGNAL_END_SEQ0 flag
+ * and the @ref NRFX_PWM_FLAG_SIGNAL_END_SEQ1 flag should be specified and
+ * the @ref NRFX_PWM_EVT_END_SEQ0 event and the @ref NRFX_PWM_EVT_END_SEQ1
+ * event should be handled in the same way).
+ *
+ * Use the @ref NRFX_PWM_FLAG_START_VIA_TASK flag if you want the playback
+ * to be only prepared by this function, and you want to start it later by
+ * triggering a task (using PPI for instance). The function will then return
+ * the address of the task to be triggered.
+ *
+ * @note The array containing the duty cycle values for the specified sequence
+ * must be in RAM and cannot be allocated on stack.
+ * For detailed information, see @ref nrf_pwm_sequence_t.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_sequence Sequence to be played back.
+ * @param[in] playback_count Number of playbacks to be performed (must not be 0).
+ * @param[in] flags Additional options. Pass any combination of
+ * @ref nrfx_pwm_flag_t "playback flags", or 0
+ * for default settings.
+ *
+ * @return Address of the task to be triggered to start the playback if the @ref
+ * NRFX_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise.
+ */
+uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_sequence_t const * p_sequence,
+ uint16_t playback_count,
+ uint32_t flags);
+
+/**
+ * @brief Function for starting a two-sequence playback.
+ *
+ * Use the @ref NRFX_PWM_FLAG_START_VIA_TASK flag if you want the playback
+ * to be only prepared by this function, and you want to start it later by
+ * triggering a task (using PPI for instance). The function will then return
+ * the address of the task to be triggered.
+ *
+ * @note The array containing the duty cycle values for the specified sequence
+ * must be in RAM and cannot be allocated on stack.
+ * For detailed information, see @ref nrf_pwm_sequence_t.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_sequence_0 First sequence to be played back.
+ * @param[in] p_sequence_1 Second sequence to be played back.
+ * @param[in] playback_count Number of playbacks to be performed (must not be 0).
+ * @param[in] flags Additional options. Pass any combination of
+ * @ref nrfx_pwm_flag_t "playback flags", or 0
+ * for default settings.
+ *
+ * @return Address of the task to be triggered to start the playback if the @ref
+ * NRFX_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise.
+ */
+uint32_t nrfx_pwm_complex_playback(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_sequence_t const * p_sequence_0,
+ nrf_pwm_sequence_t const * p_sequence_1,
+ uint16_t playback_count,
+ uint32_t flags);
+
+/**
+ * @brief Function for advancing the active sequence.
+ *
+ * This function only applies to @ref NRF_PWM_STEP_TRIGGERED mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+__STATIC_INLINE void nrfx_pwm_step(nrfx_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for stopping the sequence playback.
+ *
+ * The playback is stopped at the end of the current PWM period.
+ * This means that if the active sequence is configured to repeat each duty
+ * cycle value for a certain number of PWM periods, the last played value
+ * might appear on the output less times than requested.
+ *
+ * @note This function can be instructed to wait until the playback is stopped
+ * (by setting @p wait_until_stopped to true). Note that, depending on
+ * the length of the PMW period, this might take a significant amount of
+ * time. Alternatively, the @ref nrfx_pwm_is_stopped function can be
+ * used to poll the status, or the @ref NRFX_PWM_EVT_STOPPED event can
+ * be used to get the notification when the playback is stopped, provided
+ * the event handler is defined.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] wait_until_stopped If true, the function will not return until
+ * the playback is stopped.
+ *
+ * @retval true If the PWM peripheral is stopped.
+ * @retval false If the PWM peripheral is not stopped.
+ */
+bool nrfx_pwm_stop(nrfx_pwm_t const * const p_instance,
+ bool wait_until_stopped);
+
+/**
+ * @brief Function for checking the status of the PWM peripheral.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true If the PWM peripheral is stopped.
+ * @retval false If the PWM peripheral is not stopped.
+ */
+bool nrfx_pwm_is_stopped(nrfx_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for updating the sequence data during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id Identifier of the sequence (0 or 1).
+ * @param[in] p_sequence Pointer to the new sequence definition.
+ */
+__STATIC_INLINE void nrfx_pwm_sequence_update(
+ nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ nrf_pwm_sequence_t const * p_sequence);
+
+/**
+ * @brief Function for updating the pointer to the duty cycle values
+ * in the specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id Identifier of the sequence (0 or 1).
+ * @param[in] values New pointer to the duty cycle values.
+ */
+__STATIC_INLINE void nrfx_pwm_sequence_values_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ nrf_pwm_values_t values);
+
+/**
+ * @brief Function for updating the number of duty cycle values
+ * in the specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id Identifier of the sequence (0 or 1).
+ * @param[in] length New number of the duty cycle values.
+ */
+__STATIC_INLINE void nrfx_pwm_sequence_length_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint16_t length);
+
+/**
+ * @brief Function for updating the number of repeats for duty cycle values
+ * in specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id Identifier of the sequence (0 or 1).
+ * @param[in] repeats New number of repeats.
+ */
+__STATIC_INLINE void nrfx_pwm_sequence_repeats_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint32_t repeats);
+
+/**
+ * @brief Function for updating the additional delay after the specified
+ * sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id Identifier of the sequence (0 or 1).
+ * @param[in] end_delay New end delay value (in PWM periods).
+ */
+__STATIC_INLINE void nrfx_pwm_sequence_end_delay_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint32_t end_delay);
+
+/**
+ * @brief Function for returning the address of a specified PWM task that can
+ * be used in PPI module.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] task Requested task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_pwm_task_address_get(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_task_t task);
+
+/**@brief Function for returning the address of a specified PWM event that can
+ * be used in PPI module.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] event Requested event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_pwm_event_address_get(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_event_t event);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE void nrfx_pwm_step(nrfx_pwm_t const * const p_instance)
+{
+ nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_NEXTSTEP);
+}
+
+__STATIC_INLINE void nrfx_pwm_sequence_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ nrf_pwm_sequence_t const * p_sequence)
+{
+ nrf_pwm_sequence_set(p_instance->p_registers, seq_id, p_sequence);
+}
+
+__STATIC_INLINE void nrfx_pwm_sequence_values_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ nrf_pwm_values_t values)
+{
+ nrf_pwm_seq_ptr_set(p_instance->p_registers, seq_id, values.p_raw);
+}
+
+__STATIC_INLINE void nrfx_pwm_sequence_length_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint16_t length)
+{
+ nrf_pwm_seq_cnt_set(p_instance->p_registers, seq_id, length);
+}
+
+__STATIC_INLINE void nrfx_pwm_sequence_repeats_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint32_t repeats)
+{
+ nrf_pwm_seq_refresh_set(p_instance->p_registers, seq_id, repeats);
+}
+
+__STATIC_INLINE void nrfx_pwm_sequence_end_delay_update(nrfx_pwm_t const * const p_instance,
+ uint8_t seq_id,
+ uint32_t end_delay)
+{
+ nrf_pwm_seq_end_delay_set(p_instance->p_registers, seq_id, end_delay);
+}
+
+__STATIC_INLINE uint32_t nrfx_pwm_task_address_get(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_task_t task)
+{
+ return nrf_pwm_task_address_get(p_instance->p_registers, task);
+}
+
+__STATIC_INLINE uint32_t nrfx_pwm_event_address_get(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_event_t event)
+{
+ return nrf_pwm_event_address_get(p_instance->p_registers, event);
+}
+
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_pwm_0_irq_handler(void);
+void nrfx_pwm_1_irq_handler(void);
+void nrfx_pwm_2_irq_handler(void);
+void nrfx_pwm_3_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_PWM_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qdec.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qdec.h
new file mode 100644
index 0000000..9f636d5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qdec.h
@@ -0,0 +1,186 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_QDEC_H__
+#define NRFX_QDEC_H__
+
+#include <nrfx.h>
+#include <hal/nrf_qdec.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_qdec QDEC driver
+ * @{
+ * @ingroup nrf_qdec
+ * @brief Quadrature Decoder (QDEC) peripheral driver.
+ */
+
+/**@brief QDEC configuration structure.*/
+typedef struct
+{
+ nrf_qdec_reportper_t reportper; /**< Report period in samples. */
+ nrf_qdec_sampleper_t sampleper; /**< Sampling period in microseconds. */
+ uint32_t psela; /**< Pin number for A input. */
+ uint32_t pselb; /**< Pin number for B input. */
+ uint32_t pselled; /**< Pin number for LED output. */
+ uint32_t ledpre; /**< Time (in microseconds) how long LED is switched on before sampling. */
+ nrf_qdec_ledpol_t ledpol; /**< Active LED polarity. */
+ bool dbfen; /**< State of debouncing filter. */
+ bool sample_inten; /**< Enabling sample ready interrupt. */
+ uint8_t interrupt_priority; /**< QDEC interrupt priority. */
+} nrfx_qdec_config_t;
+
+/**@brief QDEC default configuration. */
+#define NRFX_QDEC_DEFAULT_CONFIG \
+ { \
+ .reportper = (nrf_qdec_reportper_t)NRFX_QDEC_CONFIG_REPORTPER, \
+ .sampleper = (nrf_qdec_sampleper_t)NRFX_QDEC_CONFIG_SAMPLEPER, \
+ .psela = NRFX_QDEC_CONFIG_PIO_A, \
+ .pselb = NRFX_QDEC_CONFIG_PIO_B, \
+ .pselled = NRFX_QDEC_CONFIG_PIO_LED, \
+ .ledpre = NRFX_QDEC_CONFIG_LEDPRE, \
+ .ledpol = (nrf_qdec_ledpol_t)NRFX_QDEC_CONFIG_LEDPOL, \
+ .interrupt_priority = NRFX_QDEC_CONFIG_IRQ_PRIORITY, \
+ .dbfen = NRFX_QDEC_CONFIG_DBFEN, \
+ .sample_inten = NRFX_QDEC_CONFIG_SAMPLE_INTEN \
+ }
+
+/**@brief QDEC sample event data.*/
+typedef struct
+{
+ int8_t value; /**< Sample value. */
+} nrfx_qdec_sample_data_evt_t;
+
+/**@brief QDEC report event data.*/
+typedef struct
+{
+ int16_t acc; /**< Accumulated transitions. */
+ uint16_t accdbl; /**< Accumulated double transitions. */
+} nrfx_qdec_report_data_evt_t;
+
+/**@brief QDEC event handler structure. */
+typedef struct
+{
+ nrf_qdec_event_t type;
+ union
+ {
+ nrfx_qdec_sample_data_evt_t sample; /**< Sample event data. */
+ nrfx_qdec_report_data_evt_t report; /**< Report event data. */
+ } data;
+} nrfx_qdec_event_t;
+
+/**@brief QDEC event handler.
+ * @param[in] event QDEC event structure.
+ */
+typedef void (*nrfx_qdec_event_handler_t)(nrfx_qdec_event_t event);
+
+/**@brief Function for initializing QDEC.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If QDEC was already initialized.
+ */
+nrfx_err_t nrfx_qdec_init(nrfx_qdec_config_t const * p_config,
+ nrfx_qdec_event_handler_t event_handler);
+
+/**@brief Function for uninitializing QDEC.
+ * @note Function asserts if module is uninitialized.
+ */
+void nrfx_qdec_uninit(void);
+
+/**@brief Function for enabling QDEC.
+ * @note Function asserts if module is uninitialized or enabled.
+ */
+void nrfx_qdec_enable(void);
+
+/**@brief Function for disabling QDEC.
+ * @note Function asserts if module is uninitialized or disabled.
+ */
+void nrfx_qdec_disable(void);
+
+/**@brief Function for reading accumulated transitions QDEC.
+ * @note Function asserts if module is not enabled.
+ * @note Accumulators are cleared after reading.
+ *
+ * @param[out] p_acc Pointer to store accumulated transitions.
+ * @param[out] p_accdbl Pointer to store accumulated double transitions.
+ */
+void nrfx_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl);
+
+/**
+ * @brief Function for returning the address of a specific QDEC task.
+ *
+ * @param task QDEC task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrf_qdec_task_t task)
+{
+ return (uint32_t)nrf_qdec_task_address_get(task);
+}
+
+/**
+ * @brief Function for returning the address of a specific QDEC event.
+ *
+ * @param event QDEC event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrf_qdec_event_t event)
+{
+ return (uint32_t)nrf_qdec_event_address_get(event);
+}
+
+
+void nrfx_qdec_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_QDEC_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qspi.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qspi.h
new file mode 100644
index 0000000..6f19f10
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_qspi.h
@@ -0,0 +1,297 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_QSPI_H__
+#define NRFX_QSPI_H__
+
+#include <nrfx.h>
+#include <hal/nrf_qspi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_qspi QSPI driver
+ * @{
+ * @ingroup nrf_qspi
+ * @brief Quad Serial Peripheral Interface (QSPI) peripheral driver.
+ */
+
+/**
+ * @brief QSPI driver instance configuration structure.
+ */
+typedef struct
+{
+ uint32_t xip_offset; /**< Address offset into the external memory for Execute in Place operation. */
+ nrf_qspi_pins_t pins; /**< Pins configuration structure. */
+ nrf_qspi_prot_conf_t prot_if; /**< Protocol layer interface configuration structure. */
+ nrf_qspi_phy_conf_t phy_if; /**< Physical layer interface configuration structure. */
+ uint8_t irq_priority; /**< Interrupt priority. */
+} nrfx_qspi_config_t;
+
+/**
+ * @brief QSPI instance default configuration.
+ */
+#define NRFX_QSPI_DEFAULT_CONFIG \
+{ \
+ .xip_offset = NRFX_QSPI_CONFIG_XIP_OFFSET, \
+ .pins = { \
+ .sck_pin = NRFX_QSPI_PIN_SCK, \
+ .csn_pin = NRFX_QSPI_PIN_CSN, \
+ .io0_pin = NRFX_QSPI_PIN_IO0, \
+ .io1_pin = NRFX_QSPI_PIN_IO1, \
+ .io2_pin = NRFX_QSPI_PIN_IO2, \
+ .io3_pin = NRFX_QSPI_PIN_IO3, \
+ }, \
+ .irq_priority = (uint8_t)NRFX_QSPI_CONFIG_IRQ_PRIORITY, \
+ .prot_if = { \
+ .readoc = (nrf_qspi_readoc_t)NRFX_QSPI_CONFIG_READOC, \
+ .writeoc = (nrf_qspi_writeoc_t)NRFX_QSPI_CONFIG_WRITEOC, \
+ .addrmode = (nrf_qspi_addrmode_t)NRFX_QSPI_CONFIG_ADDRMODE, \
+ .dpmconfig = false, \
+ }, \
+ .phy_if = { \
+ .sck_freq = (nrf_qspi_frequency_t)NRFX_QSPI_CONFIG_FREQUENCY, \
+ .sck_delay = (uint8_t)NRFX_QSPI_CONFIG_SCK_DELAY, \
+ .spi_mode = (nrf_qspi_spi_mode_t)NRFX_QSPI_CONFIG_MODE, \
+ .dpmen = false \
+ }, \
+}
+
+/**
+ * @brief QSPI custom instruction helper with default configuration.
+ */
+#define NRFX_QSPI_DEFAULT_CINSTR(opc, len) \
+{ \
+ .opcode = (opc), \
+ .length = (len), \
+ .io2_level = false, \
+ .io3_level = false, \
+ .wipwait = false, \
+ .wren = false \
+}
+
+/**
+ * @brief QSPI master driver event types, passed to the handler routine provided
+ * during initialization.
+ */
+typedef enum
+{
+ NRFX_QSPI_EVENT_DONE, /**< Transfer done. */
+} nrfx_qspi_evt_t;
+
+/**
+ * @brief QSPI driver event handler type.
+ */
+typedef void (*nrfx_qspi_handler_t)(nrfx_qspi_evt_t event, void * p_context);
+
+/**
+ * @brief Function for initializing the QSPI driver instance.
+ *
+ * This function configures the peripheral and its interrupts and activates it. During the
+ * activation process, the internal clocks are started and the QSPI peripheral tries to read
+ * the status byte to read the busy bit. Reading the status byte is done in a simple poll and wait
+ * mechanism.
+ * If the busy bit is 1, this indicates issues with the external memory device. As a result,
+ * @ref nrfx_qspi_init returns NRFX_ERROR_TIMEOUT.
+ *
+ * In case of issues:
+ * - Check the connection.
+ * - Make sure that the memory device does not perform other operations like erasing or writing.
+ * - Check if there is a short circuit.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] handler Event handler provided by the user. If NULL, transfers
+ * will be performed in blocking mode.
+ * @param[in] p_context Pointer to context. Use in interrupt handler.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_TIMEOUT If the peripheral cannot connect with external memory.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ * @retval NRFX_ERROR_INVALID_PARAM If the pin configuration was incorrect.
+ */
+nrfx_err_t nrfx_qspi_init(nrfx_qspi_config_t const * p_config,
+ nrfx_qspi_handler_t handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the QSPI driver instance.
+ */
+void nrfx_qspi_uninit(void);
+
+/**
+ * @brief Function for reading data from QSPI memory.
+ *
+ * Write, read, and erase operations check memory device busy state before starting the operation.
+ * If the memory is busy, the resulting action depends on the mode in which the read operation is used:
+ * - blocking mode (without handler) - a delay occurs until the last operation still runs and
+ * until operation data is still being read.
+ * - interrupt mode (with handler) - event emission occurs after the last operation
+ * and reading of data are finished.
+ *
+ * @param[out] p_rx_buffer Pointer to the receive buffer.
+ * @param[in] rx_buffer_length Size of the data to read.
+ * @param[in] src_address Address in memory to read from.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful (blocking mode) or operation
+ * was commissioned (handler mode).
+ * @retval NRFX_ERROR_BUSY If the driver currently handles another operation.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffer is not placed in the Data RAM region.
+ */
+nrfx_err_t nrfx_qspi_read(void * p_rx_buffer,
+ size_t rx_buffer_length,
+ uint32_t src_address);
+
+/**
+ * @brief Function for writing data to QSPI memory.
+ *
+ * Write, read, and erase operations check memory device busy state before starting the operation.
+ * If the memory is busy, the resulting action depends on the mode in which the write operation is used:
+ * - blocking mode (without handler) - a delay occurs until the last operation still runs and
+ * until operation data is still being sent.
+ * - interrupt mode (with handler) - event emission occurs after the last operation
+ * and sending of operation data are finished.
+ * To manually control operation execution in the memory device, use @ref nrfx_qspi_mem_busy_check
+ * after executing the write function.
+ * Remember that an incoming event signalizes only that data was sent to the memory device and the periheral
+ * before the write operation checked if memory was busy.
+ *
+ * @param[in] p_tx_buffer Pointer to the writing buffer.
+ * @param[in] tx_buffer_length Size of the data to write.
+ * @param[in] dst_address Address in memory to write to.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful (blocking mode) or operation
+ * was commissioned (handler mode).
+ * @retval NRFX_ERROR_BUSY If the driver currently handles other operation.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffer is not placed in the Data RAM region.
+ */
+nrfx_err_t nrfx_qspi_write(void const * p_tx_buffer,
+ size_t tx_buffer_length,
+ uint32_t dst_address);
+
+/**
+ * @brief Function for starting erasing of one memory block - 4KB, 64KB, or the whole chip.
+ *
+ * Write, read, and erase operations check memory device busy state before starting the operation.
+ * If the memory is busy, the resulting action depends on the mode in which the erase operation is used:
+ * - blocking mode (without handler) - a delay occurs until the last operation still runs and
+ * until operation data is still being sent.
+ * - interrupt mode (with handler) - event emission occurs after the last operation
+ * and sending of operation data are finished.
+ * To manually control operation execution in the memory device, use @ref nrfx_qspi_mem_busy_check
+ * after executing the erase function.
+ * Remember that an incoming event signalizes only that data was sent to the memory device and the periheral
+ * before the erase operation checked if memory was busy.
+ *
+ * @param[in] length Size of data to erase. See @ref nrf_qspi_erase_len_t.
+ * @param[in] start_address Memory address to start erasing. If chip erase is performed, address
+ * field is ommited.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful (blocking mode) or operation
+ * was commissioned (handler mode).
+ * @retval NRFX_ERROR_BUSY If the driver currently handles another operation.
+ */
+nrfx_err_t nrfx_qspi_erase(nrf_qspi_erase_len_t length,
+ uint32_t start_address);
+
+/**
+ * @brief Function for starting an erase operation of the whole chip.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful (blocking mode) or operation
+ * was commissioned (handler mode).
+ * @retval NRFX_ERROR_BUSY If the driver currently handles another operation.
+ */
+nrfx_err_t nrfx_qspi_chip_erase(void);
+
+/**
+ * @brief Function for getting the current driver status and status byte of memory device with
+ * testing WIP (write in progress) bit.
+ *
+ * @retval NRFX_SUCCESS If the driver and memory are ready to handle a new operation.
+ * @retval NRFX_ERROR_BUSY If the driver or memory currently handle another operation.
+ */
+nrfx_err_t nrfx_qspi_mem_busy_check(void);
+
+/**
+ * @brief Function for sending operation code, sending data, and receiving data from the memory device.
+ *
+ * Use this function to transfer configuration data to memory and to receive data from memory.
+ * Pointers can be addresses from flash memory.
+ * This function is a synchronous function and should be used only if necessary.
+ *
+ * @param[in] p_config Pointer to the structure with opcode and transfer configuration.
+ * @param[in] p_tx_buffer Pointer to the array with data to send. Can be NULL if only opcode is transmitted.
+ * @param[out] p_rx_buffer Pointer to the array for data to receive. Can be NULL if there is nothing to receive.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful.
+ * @retval NRFX_ERROR_TIMEOUT If the external memory is busy or there are connection issues.
+ * @retval NRFX_ERROR_BUSY If the driver currently handles other operation.
+ */
+nrfx_err_t nrfx_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config,
+ void const * p_tx_buffer,
+ void * p_rx_buffer);
+/**
+ * @brief Function for sending operation code and data to the memory device with simpler configuration.
+ *
+ * Use this function to transfer configuration data to memory and to receive data from memory.
+ * This function is a synchronous function and should be used only if necessary.
+ *
+ * @param[in] opcode Operation code. Sending first.
+ * @param[in] length Length of the data to send and opcode. See @ref nrf_qspi_cinstr_len_t.
+ * @param[in] p_tx_buffer Pointer to input data array.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful.
+ * @retval NRFX_ERROR_BUSY If the driver currently handles another operation.
+ */
+nrfx_err_t nrfx_qspi_cinstr_quick_send(uint8_t opcode,
+ nrf_qspi_cinstr_len_t length,
+ void const * p_tx_buffer);
+
+
+void nrfx_qspi_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_QSPI_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rng.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rng.h
new file mode 100644
index 0000000..431f872
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rng.h
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRFX_RNG_H__
+#define NRFX_RNG_H__
+
+#include <nrfx.h>
+#include <hal/nrf_rng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_rng RNG driver
+ * @{
+ * @ingroup nrf_rng
+ * @brief Random Number Generator (RNG) peripheral driver.
+ */
+
+/**
+ * @brief Struct for RNG configuration.
+ */
+typedef struct
+{
+ bool error_correction : 1; /**< Error correction flag. */
+ uint8_t interrupt_priority; /**< interrupt priority */
+} nrfx_rng_config_t;
+
+/**
+ * @brief RNG default configuration.
+ * Basic usage:
+ * @code
+ * nrfx_rng_config_t config = NRFX_RNG_DEFAULT_CONFIG;
+ * if (nrfx_rng_init(&config, handler)
+ * { ...
+ * @endcode
+ */
+#define NRFX_RNG_DEFAULT_CONFIG \
+ { \
+ .error_correction = NRFX_RNG_CONFIG_ERROR_CORRECTION, \
+ .interrupt_priority = NRFX_RNG_CONFIG_IRQ_PRIORITY, \
+ }
+
+/**
+ * @brief RNG driver event handler type.
+ */
+typedef void (* nrfx_rng_evt_handler_t)(uint8_t rng_data);
+
+/**
+ * @brief Function for initializing the nrfx_rng module.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] handler Event handler provided by the user. Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS Driver was successfully initialized.
+ * @retval NRFX_ERROR_ALREADY_INITIALIZED Driver was already initialized.
+ */
+nrfx_err_t nrfx_rng_init(nrfx_rng_config_t const * p_config, nrfx_rng_evt_handler_t handler);
+
+/**
+ * @brief Function for starting the random value generation.
+ *
+ * Function enables interrupts in perihperal and start them.
+ */
+void nrfx_rng_start(void);
+
+/**
+ * @brief Function for stoping the random value generation.
+ *
+ * Function disables interrupts in perihperal and stop generation of new random values.
+ */
+void nrfx_rng_stop(void);
+
+/**
+ * @brief Function for uninitializing the nrfx_rng module.
+ */
+void nrfx_rng_uninit(void);
+
+
+void nrfx_rng_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_RNG_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rtc.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rtc.h
new file mode 100644
index 0000000..aec1b7d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_rtc.h
@@ -0,0 +1,369 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_RTC_H__
+#define NRFX_RTC_H__
+
+#include <nrfx.h>
+#include <hal/nrf_rtc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_rtc RTC driver
+ * @{
+ * @ingroup nrf_rtc
+ * @brief Real Timer Counter (RTC) peripheral driver.
+ */
+
+/**@brief Macro to convert microseconds into ticks. */
+#define NRFX_RTC_US_TO_TICKS(us,freq) (((us) * (freq)) / 1000000U)
+
+/**@brief RTC driver interrupt types. */
+typedef enum
+{
+ NRFX_RTC_INT_COMPARE0 = 0, /**< Interrupt from COMPARE0 event. */
+ NRFX_RTC_INT_COMPARE1 = 1, /**< Interrupt from COMPARE1 event. */
+ NRFX_RTC_INT_COMPARE2 = 2, /**< Interrupt from COMPARE2 event. */
+ NRFX_RTC_INT_COMPARE3 = 3, /**< Interrupt from COMPARE3 event. */
+ NRFX_RTC_INT_TICK = 4, /**< Interrupt from TICK event. */
+ NRFX_RTC_INT_OVERFLOW = 5 /**< Interrupt from OVERFLOW event. */
+} nrfx_rtc_int_type_t;
+
+/**@brief RTC driver instance structure. */
+typedef struct
+{
+ NRF_RTC_Type * p_reg; /**< Pointer to instance register set. */
+ IRQn_Type irq; /**< Instance IRQ ID. */
+ uint8_t instance_id; /**< Instance index. */
+ uint8_t cc_channel_count; /**< Number of capture/compare channels. */
+} nrfx_rtc_t;
+
+/**@brief Macro for creating RTC driver instance.*/
+#define NRFX_RTC_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_RTC, id), \
+ .irq = NRFX_CONCAT_3(RTC, id, _IRQn), \
+ .instance_id = NRFX_CONCAT_3(NRFX_RTC, id, _INST_IDX), \
+ .cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id), \
+}
+
+enum {
+#if NRFX_CHECK(NRFX_RTC0_ENABLED)
+ NRFX_RTC0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_RTC1_ENABLED)
+ NRFX_RTC1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_RTC2_ENABLED)
+ NRFX_RTC2_INST_IDX,
+#endif
+ NRFX_RTC_ENABLED_COUNT
+};
+
+/**@brief RTC driver instance configuration structure. */
+typedef struct
+{
+ uint16_t prescaler; /**< Prescaler. */
+ uint8_t interrupt_priority; /**< Interrupt priority. */
+ uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */
+ bool reliable; /**< Reliable mode flag. */
+} nrfx_rtc_config_t;
+
+/**@brief RTC instance default configuration. */
+#define NRFX_RTC_DEFAULT_CONFIG \
+{ \
+ .prescaler = RTC_FREQ_TO_PRESCALER(NRFX_RTC_DEFAULT_CONFIG_FREQUENCY), \
+ .interrupt_priority = NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .reliable = NRFX_RTC_DEFAULT_CONFIG_RELIABLE, \
+ .tick_latency = NRFX_RTC_US_TO_TICKS(NRFX_RTC_MAXIMUM_LATENCY_US, \
+ NRFX_RTC_DEFAULT_CONFIG_FREQUENCY), \
+}
+
+/**@brief RTC driver instance handler type. */
+typedef void (*nrfx_rtc_handler_t)(nrfx_rtc_int_type_t int_type);
+
+/**@brief Function for initializing the RTC driver instance.
+ *
+ * After initialization, the instance is in power off state.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If successfully initialized.
+ * @retval NRFX_ERROR_INVALID_STATE If the instance is already initialized.
+ */
+nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
+ nrfx_rtc_config_t const * p_config,
+ nrfx_rtc_handler_t handler);
+
+/**@brief Function for uninitializing the RTC driver instance.
+ *
+ * After uninitialization, the instance is in idle state. The hardware should return to the state
+ * before initialization. The function asserts if the instance is in idle state.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for enabling the RTC driver instance.
+ *
+ * @note Function asserts if instance is enabled.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for disabling the RTC driver instance.
+ *
+ * @note Function asserts if instance is disabled.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for setting a compare channel.
+ *
+ * The function asserts if the instance is not initialized or if the channel parameter is
+ * wrong. The function powers on the instance if the instance was in power off state.
+ *
+ * The driver is not entering a critical section when configuring RTC, which means that it can be
+ * preempted for a certain amount of time. When the driver was preempted and the value to be set
+ * is short in time, there is a risk that the driver sets a compare value that is
+ * behind. If RTCn_CONFIG_RELIABLE is 1 for the given instance, the Reliable mode handles that case.
+ * However, to detect if the requested value is behind, this mode makes the following assumptions:
+ * - The maximum preemption time in ticks (8 - bit value) is known and is less than 7.7 ms
+ * (for prescaler = 0, RTC frequency 32 kHz).
+ * - The requested absolute compare value is not bigger than (0x00FFFFFF) - tick_latency. It is
+ * the user's responsibility to ensure that.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel One of the instance's channels.
+ * @param[in] val Absolute value to be set in the compare register.
+ * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_TIMEOUT If the compare was not set because the request value is behind the current counter
+ * value. This error can only be reported if RTCn_CONFIG_RELIABLE = 1.
+ */
+nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
+ uint32_t channel,
+ uint32_t val,
+ bool enable_irq);
+
+/**@brief Function for disabling a channel.
+ *
+ * This function disables channel events and channel interrupts. The function asserts if the instance is not
+ * initialized or if the channel parameter is wrong.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel One of the instance's channels.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_TIMEOUT If an interrupt was pending on the requested channel.
+ */
+nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel);
+
+/**@brief Function for enabling tick.
+ *
+ * This function enables the tick event and optionally the interrupt. The function asserts if the instance is not
+ * powered on.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
+ */
+void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq);
+
+/**@brief Function for disabling tick.
+ *
+ * This function disables the tick event and interrupt.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for enabling overflow.
+ *
+ * This function enables the overflow event and optionally the interrupt. The function asserts if the instance is
+ * not powered on.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
+ */
+void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq);
+
+/**@brief Function for disabling overflow.
+ *
+ * This function disables the overflow event and interrupt.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for getting the maximum relative ticks value that can be set in the compare channel.
+ *
+ * When a stack (for example SoftDevice) is used and it occupies high priority interrupts,
+ * the application code can be interrupted at any moment for a certain period of time.
+ * If Reliable mode is enabled, the provided maximum latency is taken into account
+ * and the return value is smaller than the RTC counter resolution.
+ * If Reliable mode is disabled, the return value equals the counter resolution.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval ticks Maximum ticks value.
+ */
+uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for disabling all instance interrupts.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_mask Pointer to the location where the mask is filled.
+ */
+__STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * const p_instance,
+ uint32_t * p_mask);
+
+/**@brief Function for enabling instance interrupts.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] mask Mask of interrupts to enable.
+ */
+__STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * const p_instance, uint32_t mask);
+
+/**@brief Function for retrieving the current counter value.
+ *
+ * This function asserts if the instance is not powered on or if p_val is NULL.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval value Counter value.
+ */
+__STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for clearing the counter value.
+ *
+ * This function asserts if the instance is not powered on.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+__STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * const p_instance);
+
+/**@brief Function for returning a requested task address for the RTC driver instance.
+ *
+ * This function asserts if the output pointer is NULL. The task address can be used by the PPI module.
+ *
+ * @param[in] p_instance Pointer to the instance.
+ * @param[in] task One of the peripheral tasks.
+ *
+ * @retval Address of task register.
+ */
+__STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * const p_instance,
+ nrf_rtc_task_t task);
+
+/**@brief Function for returning a requested event address for the RTC driver instance.
+ *
+ * This function asserts if the output pointer is NULL. The event address can be used by the PPI module.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] event One of the peripheral events.
+ *
+ * @retval Address of event register.
+ */
+__STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * const p_instance,
+ nrf_rtc_event_t event);
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * const p_instance,
+ uint32_t * p_mask)
+{
+ *p_mask = nrf_rtc_int_get(p_instance->p_reg);
+ nrf_rtc_int_disable(p_instance->p_reg, NRF_RTC_INT_TICK_MASK |
+ NRF_RTC_INT_OVERFLOW_MASK |
+ NRF_RTC_INT_COMPARE0_MASK |
+ NRF_RTC_INT_COMPARE1_MASK |
+ NRF_RTC_INT_COMPARE2_MASK |
+ NRF_RTC_INT_COMPARE3_MASK);
+}
+
+__STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * const p_instance, uint32_t mask)
+{
+ nrf_rtc_int_enable(p_instance->p_reg, mask);
+}
+
+__STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * const p_instance)
+{
+ return nrf_rtc_counter_get(p_instance->p_reg);
+}
+
+__STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * const p_instance)
+{
+ nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_CLEAR);
+}
+
+__STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * const p_instance,
+ nrf_rtc_task_t task)
+{
+ return nrf_rtc_task_address_get(p_instance->p_reg, task);
+}
+
+__STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * const p_instance,
+ nrf_rtc_event_t event)
+{
+ return nrf_rtc_event_address_get(p_instance->p_reg, event);
+}
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_rtc_0_irq_handler(void);
+void nrfx_rtc_1_irq_handler(void);
+void nrfx_rtc_2_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_RTC_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_saadc.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_saadc.h
new file mode 100644
index 0000000..76532d4
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_saadc.h
@@ -0,0 +1,326 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SAADC_H__
+#define NRFX_SAADC_H__
+
+#include <nrfx.h>
+#include <hal/nrf_saadc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_saadc SAADC driver
+ * @{
+ * @ingroup nrf_saadc
+ * @brief Successive Approximation Analog-to-Digital Converter (SAADC) peripheral driver.
+ */
+
+/**
+ * @brief Value that should be set as high limit to disable limit detection.
+ */
+#define NRFX_SAADC_LIMITH_DISABLED (2047)
+/**
+ * @brief Value that should be set as low limit to disable limit detection.
+ */
+#define NRFX_SAADC_LIMITL_DISABLED (-2048)
+
+/**
+ * @brief Macro for setting @ref nrfx_saadc_config_t to default settings.
+ */
+#define NRFX_SAADC_DEFAULT_CONFIG \
+{ \
+ .resolution = (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION, \
+ .oversample = (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE, \
+ .interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY, \
+ .low_power_mode = NRFX_SAADC_CONFIG_LP_MODE \
+}
+
+/**
+ * @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings
+ * in single ended mode.
+ *
+ * @param PIN_P Analog input.
+ */
+#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
+{ \
+ .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
+ .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
+ .gain = NRF_SAADC_GAIN1_6, \
+ .reference = NRF_SAADC_REFERENCE_INTERNAL, \
+ .acq_time = NRF_SAADC_ACQTIME_10US, \
+ .mode = NRF_SAADC_MODE_SINGLE_ENDED, \
+ .burst = NRF_SAADC_BURST_DISABLED, \
+ .pin_p = (nrf_saadc_input_t)(PIN_P), \
+ .pin_n = NRF_SAADC_INPUT_DISABLED \
+}
+
+/**
+ * @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings
+ * in differential mode.
+ *
+ * @param PIN_P Positive analog input.
+ * @param PIN_N Negative analog input.
+ */
+#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \
+{ \
+ .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
+ .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
+ .gain = NRF_SAADC_GAIN1_6, \
+ .reference = NRF_SAADC_REFERENCE_INTERNAL, \
+ .acq_time = NRF_SAADC_ACQTIME_10US, \
+ .mode = NRF_SAADC_MODE_DIFFERENTIAL, \
+ .pin_p = (nrf_saadc_input_t)(PIN_P), \
+ .pin_n = (nrf_saadc_input_t)(PIN_N) \
+}
+
+/**
+ * @brief Analog-to-digital converter driver configuration structure.
+ */
+typedef struct
+{
+ nrf_saadc_resolution_t resolution; ///< Resolution configuration.
+ nrf_saadc_oversample_t oversample; ///< Oversampling configuration.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+ bool low_power_mode; ///< Indicates if low power mode is active.
+} nrfx_saadc_config_t;
+
+/**
+ * @brief Driver event types.
+ */
+typedef enum
+{
+ NRFX_SAADC_EVT_DONE, ///< Event generated when the buffer is filled with samples.
+ NRFX_SAADC_EVT_LIMIT, ///< Event generated after one of the limits is reached.
+ NRFX_SAADC_EVT_CALIBRATEDONE ///< Event generated when the calibration is complete.
+} nrfx_saadc_evt_type_t;
+
+/**
+ * @brief Analog-to-digital converter driver done event data.
+ */
+typedef struct
+{
+ nrf_saadc_value_t * p_buffer; ///< Pointer to buffer with converted samples.
+ uint16_t size; ///< Number of samples in the buffer.
+} nrfx_saadc_done_evt_t;
+
+/**
+ * @brief Analog-to-digital converter driver limit event data.
+ */
+typedef struct
+{
+ uint8_t channel; ///< Channel on which the limit was detected.
+ nrf_saadc_limit_t limit_type; ///< Type of limit detected.
+} nrfx_saadc_limit_evt_t;
+
+/**
+ * @brief Analog-to-digital converter driver event structure.
+ */
+typedef struct
+{
+ nrfx_saadc_evt_type_t type; ///< Event type.
+ union
+ {
+ nrfx_saadc_done_evt_t done; ///< Data for @ref NRFX_SAADC_EVT_DONE event.
+ nrfx_saadc_limit_evt_t limit; ///< Data for @ref NRFX_SAADC_EVT_LIMIT event.
+ } data;
+} nrfx_saadc_evt_t;
+
+/**
+ * @brief ADC event handler.
+ *
+ * @param[in] p_event Pointer to an ADC event. The event structure is allocated on
+ * the stack, so it is valid only within the context of
+ * the event handler.
+ */
+typedef void (* nrfx_saadc_event_handler_t)(nrfx_saadc_evt_t const * p_event);
+
+/**
+ * @brief Function for initializing the SAADC.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is already initialized.
+ */
+nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
+ nrfx_saadc_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the SAADC.
+ *
+ * This function stops all ongoing conversions and disables all channels.
+ */
+void nrfx_saadc_uninit(void);
+
+
+/**
+ * @brief Function for getting the address of a SAMPLE SAADC task.
+ *
+ * @return Task address.
+ */
+uint32_t nrfx_saadc_sample_task_get(void);
+
+/**
+ * @brief Function for initializing an SAADC channel.
+ *
+ * This function configures and enables the channel.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the ADC was not initialized.
+ * @retval NRFX_ERROR_NO_MEM If the specified channel was already allocated.
+ */
+nrfx_err_t nrfx_saadc_channel_init(uint8_t channel,
+ nrf_saadc_channel_config_t const * const p_config);
+
+
+/**
+ * @brief Function for uninitializing an SAADC channel.
+ *
+ * @retval NRFX_SUCCESS If uninitialization was successful.
+ * @retval NRFX_ERROR_BUSY If the ADC is busy.
+ */
+nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel);
+
+/**
+ * @brief Function for starting SAADC sampling.
+ *
+ * @retval NRFX_SUCCESS If ADC sampling was triggered.
+ * @retval NRFX_ERROR_INVALID_STATE If ADC is in idle state.
+ */
+nrfx_err_t nrfx_saadc_sample(void);
+
+/**
+ * @brief Blocking function for executing a single ADC conversion.
+ *
+ * This function selects the desired input, starts a single conversion,
+ * waits for it to finish, and returns the result.
+ *
+ * The function will fail if ADC is busy.
+ *
+ * @param[in] channel Channel.
+ * @param[out] p_value Pointer to the location where the result should be placed.
+ *
+ * @retval NRFX_SUCCESS If conversion was successful.
+ * @retval NRFX_ERROR_BUSY If the ADC driver is busy.
+ */
+nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value);
+
+/**
+ * @brief Function for issuing conversion of data to the buffer.
+ *
+ * This function is non-blocking. The application is notified about filling the buffer by the event
+ * handler. Conversion will be done on all enabled channels. If the ADC is in idle state, the
+ * function will set up Easy DMA for the conversion. The ADC will be ready for sampling and wait for
+ * the SAMPLE task. It can be triggered manually by the @ref nrfx_saadc_sample function or by PPI
+ * using the @ref NRF_SAADC_TASK_SAMPLE task. If one buffer is already set and the conversion is
+ * ongoing, calling this function will result in queuing the given buffer. The driver will start
+ * filling the issued buffer when the first one is completed. If the function is called again before
+ * the first buffer is filled or calibration is in progress, it will return with error.
+ *
+ * @param[in] buffer Result buffer.
+ * @param[in] size Buffer size in words.
+ *
+ * @retval NRFX_SUCCESS If conversion was successful.
+ * @retval NRFX_ERROR_BUSY If the driver already has two buffers set or calibration is in progress.
+ */
+nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * buffer, uint16_t size);
+
+/**
+ * @brief Function for triggering the ADC offset calibration.
+ *
+ * This function is non-blocking. The application is notified about completion by the event handler.
+ * Calibration will also trigger DONE and RESULTDONE events.
+ *
+ * The function will fail if ADC is busy or calibration is already in progress.
+ *
+ * @retval NRFX_SUCCESS If calibration was started successfully.
+ * @retval NRFX_ERROR_BUSY If the ADC driver is busy.
+ */
+nrfx_err_t nrfx_saadc_calibrate_offset(void);
+
+/**
+ * @brief Function for retrieving the SAADC state.
+ *
+ * @retval true If the ADC is busy.
+ * @retval false If the ADC is ready.
+ */
+bool nrfx_saadc_is_busy(void);
+
+/**
+ * @brief Function for aborting ongoing and buffered conversions.
+ * @note @ref NRFX_SAADC_EVT_DONE event will be generated if there is a conversion in progress.
+ * Event will contain number of words in the sample buffer.
+ */
+void nrfx_saadc_abort(void);
+
+/**
+ * @brief Function for setting the SAADC channel limits.
+ * When limits are enabled and the result exceeds the defined bounds, the limit handler
+ * function is called.
+ *
+ * @param[in] channel SAADC channel number.
+ * @param[in] limit_low Lower limit (valid values from @ref NRFX_SAADC_LIMITL_DISABLED to
+ * @ref NRFX_SAADC_LIMITH_DISABLED). Conversion results below this value will
+ * trigger the handler function. Set to @ref NRFX_SAADC_LIMITL_DISABLED
+ * to disable this limit.
+ * @param[in] limit_high Upper limit (valid values from @ref NRFX_SAADC_LIMITL_DISABLED to
+ * @ref NRFX_SAADC_LIMITH_DISABLED). Conversion results above this value will
+ * trigger the handler function. Set to @ref NRFX_SAADC_LIMITH_DISABLED
+ * to disable this limit.
+ */
+void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high);
+
+
+void nrfx_saadc_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_SAADC_H__
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spi.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spi.h
new file mode 100644
index 0000000..edd10bc
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spi.h
@@ -0,0 +1,273 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SPI_H__
+#define NRFX_SPI_H__
+
+#include <nrfx.h>
+#include <hal/nrf_spi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_spi SPI driver
+ * @{
+ * @ingroup nrf_spi
+ * @brief SPI peripheral driver.
+ */
+
+/**
+ * @brief SPI master driver instance data structure.
+ */
+typedef struct
+{
+ NRF_SPI_Type * p_reg; ///< Pointer to a structure with SPI registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_spi_t;
+
+enum {
+#if NRFX_CHECK(NRFX_SPI0_ENABLED)
+ NRFX_SPI0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPI1_ENABLED)
+ NRFX_SPI1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPI2_ENABLED)
+ NRFX_SPI2_INST_IDX,
+#endif
+ NRFX_SPI_ENABLED_COUNT
+};
+
+/**
+ * @brief Macro for creating an SPI master driver instance.
+ */
+#define NRFX_SPI_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_SPI, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPI, id, _INST_IDX), \
+}
+
+/**
+ * @brief This value can be provided instead of a pin number for signals MOSI,
+ * MISO, and Slave Select to specify that the given signal is not used and
+ * therefore does not need to be connected to a pin.
+ */
+#define NRFX_SPI_PIN_NOT_USED 0xFF
+
+/**
+ * @brief SPI master driver instance configuration structure.
+ */
+typedef struct
+{
+ uint8_t sck_pin; ///< SCK pin number.
+ uint8_t mosi_pin; ///< MOSI pin number (optional).
+ /**< Set to @ref NRFX_SPI_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t miso_pin; ///< MISO pin number (optional).
+ /**< Set to @ref NRFX_SPI_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t ss_pin; ///< Slave Select pin number (optional).
+ /**< Set to @ref NRFX_SPI_PIN_NOT_USED
+ * if this signal is not needed. The driver
+ * supports only active low for this signal.
+ * If the signal should be active high,
+ * it must be controlled externally. */
+ uint8_t irq_priority; ///< Interrupt priority.
+ uint8_t orc; ///< Over-run character.
+ /**< This character is used when all bytes from the TX buffer are sent,
+ but the transfer continues due to RX. */
+ nrf_spi_frequency_t frequency; ///< SPI frequency.
+ nrf_spi_mode_t mode; ///< SPI mode.
+ nrf_spi_bit_order_t bit_order; ///< SPI bit order.
+} nrfx_spi_config_t;
+
+/**
+ * @brief SPI master instance default configuration.
+ */
+#define NRFX_SPI_DEFAULT_CONFIG \
+{ \
+ .sck_pin = NRFX_SPI_PIN_NOT_USED, \
+ .mosi_pin = NRFX_SPI_PIN_NOT_USED, \
+ .miso_pin = NRFX_SPI_PIN_NOT_USED, \
+ .ss_pin = NRFX_SPI_PIN_NOT_USED, \
+ .irq_priority = NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .orc = 0xFF, \
+ .frequency = NRF_SPI_FREQ_4M, \
+ .mode = NRF_SPI_MODE_0, \
+ .bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST, \
+}
+
+/**
+ * @brief Single transfer descriptor structure.
+ */
+typedef struct
+{
+ uint8_t const * p_tx_buffer; ///< Pointer to TX buffer.
+ size_t tx_length; ///< TX buffer length.
+ uint8_t * p_rx_buffer; ///< Pointer to RX buffer.
+ size_t rx_length; ///< RX buffer length.
+} nrfx_spi_xfer_desc_t;
+
+/**
+ * @brief Macro for setting up single transfer descriptor.
+ *
+ * This macro is for internal use only.
+ */
+#define NRFX_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
+ { \
+ .p_tx_buffer = (uint8_t const *)(p_tx), \
+ .tx_length = (tx_len), \
+ .p_rx_buffer = (p_rx), \
+ .rx_length = (rx_len), \
+ }
+
+/**
+ * @brief Macro for setting duplex TX RX transfer.
+ */
+#define NRFX_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
+ NRFX_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
+
+/**
+ * @brief Macro for setting TX transfer.
+ */
+#define NRFX_SPI_XFER_TX(p_buf, length) \
+ NRFX_SPI_SINGLE_XFER(p_buf, length, NULL, 0)
+
+/**
+ * @brief Macro for setting RX transfer.
+ */
+#define NRFX_SPI_XFER_RX(p_buf, length) \
+ NRFX_SPI_SINGLE_XFER(NULL, 0, p_buf, length)
+
+/**
+ * @brief SPI master driver event types, passed to the handler routine provided
+ * during initialization.
+ */
+typedef enum
+{
+ NRFX_SPI_EVENT_DONE, ///< Transfer done.
+} nrfx_spi_evt_type_t;
+
+typedef struct
+{
+ nrfx_spi_evt_type_t type; ///< Event type.
+ nrfx_spi_xfer_desc_t xfer_desc; ///< Transfer details.
+} nrfx_spi_evt_t;
+
+/**
+ * @brief SPI master driver event handler type.
+ */
+typedef void (* nrfx_spi_evt_handler_t)(nrfx_spi_evt_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the SPI master driver instance.
+ *
+ * This function configures and enables the specified peripheral.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ *
+ * @param handler Event handler provided by the user. If NULL, transfers
+ * will be performed in blocking mode.
+ * @param p_context Context passed to event handler.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_spi_init(nrfx_spi_t const * const p_instance,
+ nrfx_spi_config_t const * p_config,
+ nrfx_spi_evt_handler_t handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the SPI master driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spi_uninit(nrfx_spi_t const * const p_instance);
+
+/**
+ * @brief Function for starting the SPI data transfer.
+ *
+ * If an event handler was provided in the @ref nrfx_spi_init call, this function
+ * returns immediately and the handler is called when the transfer is done.
+ * Otherwise, the transfer is performed in blocking mode, which means that this function
+ * returns when the transfer is finished.
+ *
+ * @param p_instance Pointer to the driver instance structure.
+ * @param p_xfer_desc Pointer to the transfer descriptor.
+ * @param flags Transfer options (0 for default settings).
+ * Currently, no additional flags are available.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ */
+nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * const p_instance,
+ nrfx_spi_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags);
+
+/**
+ * @brief Function for aborting ongoing transfer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spi_abort(nrfx_spi_t const * p_instance);
+
+
+void nrfx_spi_0_irq_handler(void);
+void nrfx_spi_1_irq_handler(void);
+void nrfx_spi_2_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_SPI_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spim.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spim.h
new file mode 100644
index 0000000..3490f11
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spim.h
@@ -0,0 +1,396 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SPIM_H__
+#define NRFX_SPIM_H__
+
+#include <nrfx.h>
+#include <hal/nrf_spim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_spim SPIM driver
+ * @{
+ * @ingroup nrf_spim
+ * @brief SPIM peripheral driver.
+ */
+
+/**
+ * @brief SPIM master driver instance data structure.
+ */
+typedef struct
+{
+ NRF_SPIM_Type * p_reg; ///< Pointer to a structure with SPIM registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_spim_t;
+
+enum {
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+ NRFX_SPIM0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+ NRFX_SPIM1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+ NRFX_SPIM2_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+ NRFX_SPIM3_INST_IDX,
+#endif
+ NRFX_SPIM_ENABLED_COUNT
+};
+
+/**
+ * @brief Macro for creating an SPIM master driver instance.
+ */
+#define NRFX_SPIM_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_SPIM, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIM, id, _INST_IDX), \
+}
+
+/**
+ * @brief This value can be provided instead of a pin number for signals MOSI,
+ * MISO, and Slave Select to specify that the given signal is not used and
+ * therefore does not need to be connected to a pin.
+ */
+#define NRFX_SPIM_PIN_NOT_USED 0xFF
+
+/**
+ * @brief SPIM master driver instance configuration structure.
+ */
+typedef struct
+{
+ uint8_t sck_pin; ///< SCK pin number.
+ uint8_t mosi_pin; ///< MOSI pin number (optional).
+ /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t miso_pin; ///< MISO pin number (optional).
+ /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint8_t ss_pin; ///< Slave Select pin number (optional).
+ /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+ * if this signal is not needed. */
+ bool ss_active_high; ///< Polarity of the Slave Select pin during transmission.
+ uint8_t irq_priority; ///< Interrupt priority.
+ uint8_t orc; ///< Over-run character.
+ /**< This character is used when all bytes from the TX buffer are sent,
+ but the transfer continues due to RX. */
+ nrf_spim_frequency_t frequency; ///< SPI frequency.
+ nrf_spim_mode_t mode; ///< SPI mode.
+ nrf_spim_bit_order_t bit_order; ///< SPI bit order.
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+ uint8_t dcx_pin; ///< D/CX pin number (optional).
+ uint8_t rx_delay; ///< Sample delay for input serial data on MISO.
+ /**< The value specifies the delay, in number of 64 MHz clock cycles
+ * (15.625 ns), from the the sampling edge of SCK (leading edge for
+ * CONFIG.CPHA = 0, trailing edge for CONFIG.CPHA = 1) until
+ * the input serial data is sampled.*/
+ bool use_hw_ss; ///< Indication to use software or hardware controlled Slave Select pin.
+ uint8_t ss_duration; ///< Slave Select duration before and after transmission.
+ /**< Minimum duration between the edge of CSN and the edge of SCK and minimum
+ * duration of CSN must stay inactive between transactions.
+ * The value is specified in number of 64 MHz clock cycles (15.625 ns).
+ * Supported only for hardware controlled Slave Select.*/
+#endif
+} nrfx_spim_config_t;
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief SPIM master instance extended default configuration.
+ */
+ #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
+ .dcx_pin = NRFX_SPIM_PIN_NOT_USED, \
+ .rx_delay = 0x00, \
+ .ss_duration = 0x00, \
+ .use_hw_ss = false,
+#else
+ #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
+#endif
+
+/**
+ * @brief SPIM master instance default configuration.
+ */
+#define NRFX_SPIM_DEFAULT_CONFIG \
+{ \
+ .sck_pin = NRFX_SPIM_PIN_NOT_USED, \
+ .mosi_pin = NRFX_SPIM_PIN_NOT_USED, \
+ .miso_pin = NRFX_SPIM_PIN_NOT_USED, \
+ .ss_pin = NRFX_SPIM_PIN_NOT_USED, \
+ .ss_active_high = false, \
+ .irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .orc = 0xFF, \
+ .frequency = NRF_SPIM_FREQ_4M, \
+ .mode = NRF_SPIM_MODE_0, \
+ .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, \
+ NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
+}
+
+#define NRFX_SPIM_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */
+#define NRFX_SPIM_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */
+#define NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */
+#define NRFX_SPIM_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */
+#define NRFX_SPIM_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */
+
+/**
+ * @brief Single transfer descriptor structure.
+ */
+typedef struct
+{
+ uint8_t const * p_tx_buffer; ///< Pointer to TX buffer.
+ size_t tx_length; ///< TX buffer length.
+ uint8_t * p_rx_buffer; ///< Pointer to RX buffer.
+ size_t rx_length; ///< RX buffer length.
+} nrfx_spim_xfer_desc_t;
+
+/**
+ * @brief Macro for setting up single transfer descriptor.
+ *
+ * This macro is for internal use only.
+ */
+#define NRFX_SPIM_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
+ { \
+ .p_tx_buffer = (uint8_t const *)(p_tx), \
+ .tx_length = (tx_len), \
+ .p_rx_buffer = (p_rx), \
+ .rx_length = (rx_len), \
+ }
+
+/**
+ * @brief Macro for setting duplex TX RX transfer.
+ */
+#define NRFX_SPIM_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
+ NRFX_SPIM_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
+
+/**
+ * @brief Macro for setting TX transfer.
+ */
+#define NRFX_SPIM_XFER_TX(p_buf, length) \
+ NRFX_SPIM_SINGLE_XFER(p_buf, length, NULL, 0)
+
+/**
+ * @brief Macro for setting RX transfer.
+ */
+#define NRFX_SPIM_XFER_RX(p_buf, length) \
+ NRFX_SPIM_SINGLE_XFER(NULL, 0, p_buf, length)
+
+/**
+ * @brief SPIM master driver event types, passed to the handler routine provided
+ * during initialization.
+ */
+typedef enum
+{
+ NRFX_SPIM_EVENT_DONE, ///< Transfer done.
+} nrfx_spim_evt_type_t;
+
+typedef struct
+{
+ nrfx_spim_evt_type_t type; ///< Event type.
+ nrfx_spim_xfer_desc_t xfer_desc; ///< Transfer details.
+} nrfx_spim_evt_t;
+
+/**
+ * @brief SPIM master driver event handler type.
+ */
+typedef void (* nrfx_spim_evt_handler_t)(nrfx_spim_evt_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the SPI master driver instance.
+ *
+ * This function configures and enables the specified peripheral.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ *
+ * @param handler Event handler provided by the user. If NULL, transfers
+ * will be performed in blocking mode.
+ * @param p_context Context passed to event handler.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If requested configuration is not supported
+ * by the SPIM instance.
+ */
+nrfx_err_t nrfx_spim_init(nrfx_spim_t const * const p_instance,
+ nrfx_spim_config_t const * p_config,
+ nrfx_spim_evt_handler_t handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the SPI master driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spim_uninit(nrfx_spim_t const * const p_instance);
+
+/**
+ * @brief Function for starting the SPI data transfer.
+ *
+ * Additional options are provided using the @c flags parameter:
+ *
+ * - @ref NRFX_SPIM_FLAG_TX_POSTINC and @ref NRFX_SPIM_FLAG_RX_POSTINC<span></span>:
+ * Post-incrementation of buffer addresses. Supported only by SPIM.
+ * - @ref NRFX_SPIM_FLAG_HOLD_XFER<span></span>: Driver is not starting the transfer. Use this
+ * flag if the transfer is triggered externally by PPI. Supported only by SPIM. Use
+ * @ref nrfx_spim_start_task_get to get the address of the start task.
+ * - @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER<span></span>: No user event handler after transfer
+ * completion. This also means no interrupt at the end of the transfer. Supported only by SPIM.
+ * If @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into
+ * busy state, so you must ensure that the next transfers are set up when SPIM is not active.
+ * @ref nrfx_spim_end_event_get function can be used to detect end of transfer. Option can be used
+ * together with @ref NRFX_SPIM_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers
+ * without interruptions.
+ * - @ref NRFX_SPIM_FLAG_REPEATED_XFER<span></span>: Prepare for repeated transfers. You can set
+ * up a number of transfers that will be triggered externally (for example by PPI). An example is
+ * a TXRX transfer with the options @ref NRFX_SPIM_FLAG_RX_POSTINC,
+ * @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_SPIM_FLAG_REPEATED_XFER. After the
+ * transfer is set up, a set of transfers can be triggered by PPI that will read, for example,
+ * the same register of an external component and put it into a RAM buffer without any interrupts.
+ * @ref nrfx_spim_end_event_get can be used to get the address of the END event, which can be
+ * used to count the number of transfers. If @ref NRFX_SPIM_FLAG_REPEATED_XFER is used,
+ * the driver does not set the instance into busy state, so you must ensure that the next
+ * transfers are set up when SPIM is not active. Supported only by SPIM.
+ *
+ * @note Peripherals using EasyDMA (including SPIM) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param p_instance Pointer to the driver instance structure.
+ * @param p_xfer_desc Pointer to the transfer descriptor.
+ * @param flags Transfer options (0 for default settings).
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data
+ * RAM region.
+ */
+nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * const p_instance,
+ nrfx_spim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags);
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for starting the SPI data transfer with DCX control.
+ *
+ * See @ref nrfx_spim_xfer for description of additional options of transfer
+ * provided by the @c flags parameter.
+ *
+ * @note Peripherals that use EasyDMA (including SPIM) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param p_instance Pointer to the driver instance structure.
+ * @param p_xfer_desc Pointer to the transfer descriptor.
+ * @param flags Transfer options (0 for default settings).
+ * @param cmd_length Length of the command bytes preceding the data
+ * bytes. The DCX line will be low during transmission
+ * of command bytes and high during transmission of data bytes.
+ * Maximum value available for dividing the transmitted bytes
+ * into command bytes and data bytes is @ref NRF_SPIM_DCX_CNT_ALL_CMD - 1.
+ * The @ref NRF_SPIM_DCX_CNT_ALL_CMD value passed as the
+ * @c cmd_length parameter causes all transmitted bytes
+ * to be marked as command bytes.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data
+ * RAM region.
+ */
+nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * const p_instance,
+ nrfx_spim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags,
+ uint8_t cmd_length);
+#endif
+
+/**
+ * @brief Function for returning the address of a SPIM start task.
+ *
+ * This function should be used if @ref nrfx_spim_xfer was called with the flag @ref NRFX_SPIM_FLAG_HOLD_XFER.
+ * In that case, the transfer is not started by the driver, but it must be started externally by PPI.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return Start task address.
+ */
+uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance);
+
+/**
+ * @brief Function for returning the address of a END SPIM event.
+ *
+ * The END event can be used to detect the end of a transfer
+ * if the @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER option is used.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return END event address.
+ */
+uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance);
+
+/**
+ * @brief Function for aborting ongoing transfer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spim_abort(nrfx_spim_t const * p_instance);
+
+
+void nrfx_spim_0_irq_handler(void);
+void nrfx_spim_1_irq_handler(void);
+void nrfx_spim_2_irq_handler(void);
+void nrfx_spim_3_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_SPIM_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spis.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spis.h
new file mode 100644
index 0000000..b16b29f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_spis.h
@@ -0,0 +1,250 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SPIS_H__
+#define NRFX_SPIS_H__
+
+#include <nrfx.h>
+#include <hal/nrf_spis.h>
+#include <hal/nrf_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_spis SPI slave driver
+ * @{
+ * @ingroup nrf_spis
+ * @brief SPI Slave peripheral driver.
+ */
+
+/** @brief SPI slave driver instance data structure. */
+typedef struct
+{
+ NRF_SPIS_Type * p_reg; //!< Pointer to a structure with SPIS registers.
+ uint8_t drv_inst_idx; //!< Driver instance index.
+} nrfx_spis_t;
+
+enum {
+#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
+ NRFX_SPIS0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
+ NRFX_SPIS1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
+ NRFX_SPIS2_INST_IDX,
+#endif
+ NRFX_SPIS_ENABLED_COUNT
+};
+
+/** @brief Macro for creating an SPI slave driver instance. */
+#define NRFX_SPIS_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_SPIS, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIS, id, _INST_IDX), \
+}
+
+/**
+ * @brief This value can be provided instead of a pin number for the signals MOSI
+ * and MISO to specify that the given signal is not used and therefore
+ * does not need to be connected to a pin.
+ */
+#define NRFX_SPIS_PIN_NOT_USED 0xFF
+
+/** @brief Default pull-up configuration of the SPI CS. */
+#define NRFX_SPIS_DEFAULT_CSN_PULLUP NRF_GPIO_PIN_NOPULL
+/** @brief Default drive configuration of the SPI MISO. */
+#define NRFX_SPIS_DEFAULT_MISO_DRIVE NRF_GPIO_PIN_S0S1
+
+/** @brief SPI slave driver event types. */
+typedef enum
+{
+ NRFX_SPIS_BUFFERS_SET_DONE, //!< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transaction can be done.
+ NRFX_SPIS_XFER_DONE, //!< SPI transaction event. SPI transaction has been completed.
+ NRFX_SPIS_EVT_TYPE_MAX //!< Enumeration upper bound.
+} nrfx_spis_evt_type_t;
+
+/** @brief SPI slave driver event structure. */
+typedef struct
+{
+ nrfx_spis_evt_type_t evt_type; //!< Type of the event.
+ size_t rx_amount; //!< Number of bytes received in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events.
+ size_t tx_amount; //!< Number of bytes transmitted in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events.
+} nrfx_spis_evt_t;
+
+/** @brief SPI slave instance default configuration. */
+#define NRFX_SPIS_DEFAULT_CONFIG \
+{ \
+ .sck_pin = NRFX_SPIS_PIN_NOT_USED, \
+ .mosi_pin = NRFX_SPIS_PIN_NOT_USED, \
+ .miso_pin = NRFX_SPIS_PIN_NOT_USED, \
+ .csn_pin = NRFX_SPIS_PIN_NOT_USED, \
+ .mode = NRF_SPIS_MODE_0, \
+ .bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, \
+ .csn_pullup = NRFX_SPIS_DEFAULT_CSN_PULLUP, \
+ .miso_drive = NRFX_SPIS_DEFAULT_MISO_DRIVE, \
+ .def = NRFX_SPIS_DEFAULT_DEF, \
+ .orc = NRFX_SPIS_DEFAULT_ORC, \
+ .irq_priority = NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY, \
+}
+
+/** @brief SPI peripheral device configuration data. */
+typedef struct
+{
+ uint32_t miso_pin; //!< SPI MISO pin (optional).
+ /**< Set @ref NRFX_SPIS_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint32_t mosi_pin; //!< SPI MOSI pin (optional).
+ /**< Set @ref NRFX_SPIS_PIN_NOT_USED
+ * if this signal is not needed. */
+ uint32_t sck_pin; //!< SPI SCK pin.
+ uint32_t csn_pin; //!< SPI CSN pin.
+ nrf_spis_mode_t mode; //!< SPI mode.
+ nrf_spis_bit_order_t bit_order; //!< SPI transaction bit order.
+ nrf_gpio_pin_pull_t csn_pullup; //!< CSN pin pull-up configuration.
+ nrf_gpio_pin_drive_t miso_drive; //!< MISO pin drive configuration.
+ uint8_t def; //!< Character clocked out in case of an ignored transaction.
+ uint8_t orc; //!< Character clocked out after an over-read of the transmit buffer.
+ uint8_t irq_priority; //!< Interrupt priority.
+} nrfx_spis_config_t;
+
+
+/**
+ * @brief SPI slave driver event handler type.
+ *
+ * @param[in] p_event Pointer to the event structure. The structure is
+ * allocated on the stack so it is valid only until
+ * the event handler returns.
+ * @param[in] p_context Context set on initialization.
+ */
+typedef void (*nrfx_spis_event_handler_t)(nrfx_spis_evt_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the SPI slave driver instance.
+ *
+ * @note When the nRF52 Anomaly 109 workaround for SPIS is enabled, this function
+ * initializes the GPIOTE driver as well, and uses one of GPIOTE channels
+ * to detect falling edges on CSN pin.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Function to be called by the SPI slave driver upon event.
+ * Must not be NULL.
+ * @param[in] p_context Context passed to the event handler.
+ *
+ * @retval NRFX_SUCCESS If the initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the instance is already initialized.
+ * @retval NRFX_ERROR_INVALID_PARAM If an invalid parameter is supplied.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ * @retval NRFX_ERROR_INTERNAL GPIOTE channel for detecting falling edges
+ * on CSN pin cannot be initialized. Possible
+ * only when using nRF52 Anomaly 109 workaround.
+ */
+nrfx_err_t nrfx_spis_init(nrfx_spis_t const * const p_instance,
+ nrfx_spis_config_t const * p_config,
+ nrfx_spis_event_handler_t event_handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the SPI slave driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spis_uninit(nrfx_spis_t const * const p_instance);
+
+/**
+ * @brief Function for preparing the SPI slave instance for a single SPI transaction.
+ *
+ * This function prepares the SPI slave device to be ready for a single SPI transaction. It configures
+ * the SPI slave device to use the memory supplied with the function call in SPI transactions.
+ *
+ * When either the memory buffer configuration or the SPI transaction has been
+ * completed, the event callback function will be called with the appropriate event
+ * @ref nrfx_spis_evt_type_t. Note that the callback function can be called before returning from
+ * this function, because it is called from the SPI slave interrupt context.
+ *
+ * @note This function can be called from the callback function context.
+ *
+ * @note Client applications must call this function after every @ref NRFX_SPIS_XFER_DONE event if
+ * the SPI slave driver should be prepared for a possible new SPI transaction.
+ *
+ * @note Peripherals using EasyDMA (including SPIS) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_tx_buffer Pointer to the TX buffer. Can be NULL when the buffer length is zero.
+ * @param[in] p_rx_buffer Pointer to the RX buffer. Can be NULL when the buffer length is zero.
+ * @param[in] tx_buffer_length Length of the TX buffer in bytes.
+ * @param[in] rx_buffer_length Length of the RX buffer in bytes.
+ *
+ * @retval NRFX_SUCCESS If the operation was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the operation failed because the SPI slave device is in an incorrect state.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data
+ * RAM region.
+ * @retval NRFX_ERROR_INVALID_LENGTH If provided lengths exceed the EasyDMA limits for the peripheral.
+ * @retval NRFX_ERROR_INTERNAL If the operation failed because of an internal error.
+ */
+nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * const p_instance,
+ uint8_t const * p_tx_buffer,
+ size_t tx_buffer_length,
+ uint8_t * p_rx_buffer,
+ size_t rx_buffer_length);
+
+
+void nrfx_spis_0_irq_handler(void);
+void nrfx_spis_1_irq_handler(void);
+void nrfx_spis_2_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_SPIS_H__
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_swi.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_swi.h
new file mode 100644
index 0000000..92416ae
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_swi.h
@@ -0,0 +1,222 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SWI_H__
+#define NRFX_SWI_H__
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_EGU_ENABLED)
+#include <hal/nrf_egu.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_swi SWI driver
+ * @{
+ * @ingroup nrf_swi_egu
+ *
+ * @brief Driver for managing software interrupts (SWI).
+ */
+
+/** @brief SWI instance. */
+typedef uint8_t nrfx_swi_t;
+
+/**
+ * @brief SWI user flags.
+ *
+ * User flags are set during the SWI trigger and passed to the callback function as an argument.
+ */
+typedef uint16_t nrfx_swi_flags_t;
+
+/** @brief Unallocated instance value. */
+#define NRFX_SWI_UNALLOCATED ((nrfx_swi_t)0xFFuL)
+
+/** @brief Default SWI priority. */
+#define NRFX_SWI_DEFAULT_PRIORITY APP_IRQ_PRIORITY_LOWEST
+
+/**
+ * @brief SWI handler function.
+ *
+ * @param swi SWI instance.
+ * @param flags User flags.
+ */
+typedef void (*nrfx_swi_handler_t)(nrfx_swi_t swi, nrfx_swi_flags_t flags);
+
+
+/**
+ * @brief Function for allocating the first unused SWI instance and setting a handler.
+ *
+ * @param[out] p_swi Points to a place where the allocated SWI instance
+ * number is to be stored.
+ * @param[in] event_handler Event handler function.
+ * If NULL, no interrupt will be enabled.
+ * It can be NULL only if the EGU driver is enabled.
+ * For classic SWI, it must be a valid handler pointer.
+ * @param[in] irq_priority Interrupt priority.
+ *
+ * @retval NRFX_SUCCESS If the SWI was successfully allocated.
+ * @retval NRFX_ERROR_NO_MEM If there is no available SWI to be used.
+ */
+nrfx_err_t nrfx_swi_alloc(nrfx_swi_t * p_swi,
+ nrfx_swi_handler_t event_handler,
+ uint32_t irq_priority);
+
+/**
+ * @brief Function for freeing a previously allocated SWI.
+ *
+ * @param[in,out] p_swi SWI instance to free. The value is changed to
+ * @ref NRFX_SWI_UNALLOCATED on success.
+ */
+void nrfx_swi_free(nrfx_swi_t * p_swi);
+
+/** @brief Function for freeing all allocated SWIs. */
+void nrfx_swi_all_free(void);
+
+/**
+ * @brief Function for triggering the SWI.
+ *
+ * @param[in] swi SWI to trigger.
+ * @param[in] flag_number Number of user flag to trigger.
+ */
+void nrfx_swi_trigger(nrfx_swi_t swi,
+ uint8_t flag_number);
+
+/**
+ * @brief Function for checking if the specified SWI is currently allocated.
+ *
+ * @param[in] swi SWI instance.
+ *
+ * @retval true If the SWI instance is allocated.
+ * @retval false Otherwise.
+ */
+bool nrfx_swi_is_allocated(nrfx_swi_t swi);
+
+#if NRFX_CHECK(NRFX_EGU_ENABLED) || defined(__NRFX_DOXYGEN__)
+
+/**
+ * @brief Function for returning the base address of the EGU peripheral
+ * associated with the specified SWI instance.
+ *
+ * @param[in] swi SWI instance.
+ *
+ * @returns EGU base address or NULL if the specified SWI instance number
+ * is too high.
+ */
+__STATIC_INLINE NRF_EGU_Type * nrfx_swi_egu_instance_get(nrfx_swi_t swi)
+{
+#if (EGU_COUNT < SWI_COUNT)
+ if (swi >= EGU_COUNT)
+ {
+ return NULL;
+ }
+#endif
+ uint32_t offset = ((uint32_t)swi) * (NRF_EGU1_BASE - NRF_EGU0_BASE);
+ return (NRF_EGU_Type *)(NRF_EGU0_BASE + offset);
+}
+
+/**
+ * @brief Function for returning the EGU trigger task address.
+ *
+ * @param[in] swi SWI instance.
+ * @param[in] channel Number of the EGU channel.
+ *
+ * @returns Address of EGU trigger task.
+ */
+__STATIC_INLINE uint32_t nrfx_swi_task_trigger_address_get(nrfx_swi_t swi,
+ uint8_t channel)
+{
+ NRFX_ASSERT(nrfx_swi_is_allocated(swi));
+
+ NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
+#if (EGU_COUNT < SWI_COUNT)
+ if (p_egu == NULL)
+ {
+ return 0;
+ }
+#endif
+
+ return (uint32_t)nrf_egu_task_trigger_address_get(p_egu, channel);
+}
+
+/**
+ * @brief Function for returning the EGU triggered event address.
+ *
+ * @param[in] swi SWI instance.
+ * @param[in] channel Number of the EGU channel.
+ *
+ * @returns Address of EGU triggered event.
+ */
+__STATIC_INLINE uint32_t nrfx_swi_event_triggered_address_get(nrfx_swi_t swi,
+ uint8_t channel)
+{
+ NRFX_ASSERT(nrfx_swi_is_allocated(swi));
+
+ NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
+#if (EGU_COUNT < SWI_COUNT)
+ if (p_egu == NULL)
+ {
+ return 0;
+ }
+#endif
+
+ return (uint32_t)nrf_egu_event_triggered_address_get(p_egu, channel);
+}
+
+#endif // NRFX_CHECK(NRFX_EGU_ENABLED) || defined(__NRFX_DOXYGEN__)
+
+
+void nrfx_swi_0_irq_handler(void);
+void nrfx_swi_1_irq_handler(void);
+void nrfx_swi_2_irq_handler(void);
+void nrfx_swi_3_irq_handler(void);
+void nrfx_swi_4_irq_handler(void);
+void nrfx_swi_5_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_SWI_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_systick.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_systick.h
new file mode 100644
index 0000000..1629074
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_systick.h
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_SYSTICK_H__
+#define NRFX_SYSTICK_H__
+
+#include <nrfx.h>
+#include <hal/nrf_systick.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_systick ARM(R) SysTick driver
+ * @{
+ * @ingroup nrf_systick
+ *
+ * @brief ARM(R) SysTick driver.
+ *
+ * This driver configures ARM(R) SysTick as a free-running timer.
+ * This timer is used to generate delays and pool for timeouts.
+ * Only relatively short timeouts are supported.
+ * The SysTick works on 64MHz and is 24-bits wide.
+ * It means that it overflows around 4 times per second and around 250&nbsp;ms
+ * would be the highest supported time in the library.
+ * But it would be really hard to detect if overflow was generated without
+ * using interrupts. For safety we would limit the maximum delay range by half.
+ */
+
+/**
+ * @brief The value type that holds the SysTick state
+ *
+ * This variable is used to count the requested timeout.
+ * @sa nrfx_systick_get
+ */
+typedef struct {
+ uint32_t time; //!< Registered time value
+} nrfx_systick_state_t;
+
+/**
+ * @brief Configure and start the timer
+ *
+ * Function configures SysTick as a free-running timer without interrupt.
+ */
+void nrfx_systick_init(void);
+
+/**
+ * @brief Get current SysTick state
+ *
+ * Function gets current state of the SysTick timer.
+ * It can be used to check time-out by @ref nrfx_systick_test.
+ *
+ * @param[out] p_state The pointer to the state variable to be filled
+ */
+void nrfx_systick_get(nrfx_systick_state_t * p_state);
+
+/**
+ * @brief Test if specified time is up in relation to remembered state
+ *
+ * @param[in] p_state Remembered state set by @ref nrfx_systick_get
+ * @param[in] us Required time-out.
+ *
+ * @retval true If current time is higher than specified state plus given time-out.
+ * @retval false If current time is lower than specified state plus given time-out
+ */
+bool nrfx_systick_test(nrfx_systick_state_t const * p_state, uint32_t us);
+
+/**
+ * @brief Blocking delay in CPU ticks
+ *
+ * @param[in] ticks Number of CPU ticks to delay.
+ */
+void nrfx_systick_delay_ticks(uint32_t ticks);
+
+/**
+ * @brief Blocking delay in us
+ *
+ * @param[in] us Number of microseconds to delay.
+ */
+void nrfx_systick_delay_us(uint32_t us);
+
+/**
+ * @brief Blocking delay in ms
+ *
+ * This delay function removes the limits of the highest possible delay value.
+ *
+ * @param[in] ms Number of milliseconds to delay.
+ */
+void nrfx_systick_delay_ms(uint32_t ms);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRFX_SYSTICK_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_timer.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_timer.h
new file mode 100644
index 0000000..b493f23
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_timer.h
@@ -0,0 +1,413 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_TIMER_H__
+#define NRFX_TIMER_H__
+
+#include <nrfx.h>
+#include <hal/nrf_timer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_timer Timer driver
+ * @{
+ * @ingroup nrf_timer
+ * @brief TIMER peripheral driver.
+ */
+
+/**
+ * @brief Timer driver instance data structure.
+ */
+typedef struct
+{
+ NRF_TIMER_Type * p_reg; ///< Pointer to the structure with TIMER peripheral instance registers.
+ uint8_t instance_id; ///< Driver instance index.
+ uint8_t cc_channel_count; ///< Number of capture/compare channels.
+} nrfx_timer_t;
+
+/**
+ * @brief Macro for creating a timer driver instance.
+ */
+#define NRFX_TIMER_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_TIMER, id), \
+ .instance_id = NRFX_CONCAT_3(NRFX_TIMER, id, _INST_IDX), \
+ .cc_channel_count = NRF_TIMER_CC_CHANNEL_COUNT(id), \
+}
+
+enum {
+#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
+ NRFX_TIMER0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
+ NRFX_TIMER1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TIMER2_ENABLED)
+ NRFX_TIMER2_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TIMER3_ENABLED)
+ NRFX_TIMER3_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TIMER4_ENABLED)
+ NRFX_TIMER4_INST_IDX,
+#endif
+ NRFX_TIMER_ENABLED_COUNT
+};
+
+/**
+ * @brief Timer driver instance configuration structure.
+ */
+typedef struct
+{
+ nrf_timer_frequency_t frequency; ///< Frequency.
+ nrf_timer_mode_t mode; ///< Mode of operation.
+ nrf_timer_bit_width_t bit_width; ///< Bit width.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+ void * p_context; ///< Context passed to interrupt handler.
+} nrfx_timer_config_t;
+
+/**
+ * @brief Timer driver instance default configuration.
+ */
+#define NRFX_TIMER_DEFAULT_CONFIG \
+{ \
+ .frequency = (nrf_timer_frequency_t)NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY,\
+ .mode = (nrf_timer_mode_t)NRFX_TIMER_DEFAULT_CONFIG_MODE, \
+ .bit_width = (nrf_timer_bit_width_t)NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH,\
+ .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .p_context = NULL \
+}
+
+/**
+ * @brief Timer driver event handler type.
+ *
+ * @param[in] event_type Timer event.
+ * @param[in] p_context General purpose parameter set during initialization of
+ * the timer. This parameter can be used to pass
+ * additional information to the handler function, for
+ * example, the timer ID.
+ */
+typedef void (* nrfx_timer_event_handler_t)(nrf_timer_event_t event_type,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] timer_event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the instance is already initialized.
+ */
+nrfx_err_t nrfx_timer_init(nrfx_timer_t const * const p_instance,
+ nrfx_timer_config_t const * p_config,
+ nrfx_timer_event_handler_t timer_event_handler);
+
+/**
+ * @brief Function for uninitializing the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_uninit(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for turning on the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_enable(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for turning off the timer.
+ *
+ * Note that the timer will allow to enter the lowest possible SYSTEM_ON state
+ * only after this function is called.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_disable(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for checking the timer state.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return True if timer is enabled, false otherwise.
+ */
+bool nrfx_timer_is_enabled(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for pausing the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_pause(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for resuming the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_resume(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for clearing the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_clear(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for incrementing the timer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_timer_increment(nrfx_timer_t const * const p_instance);
+
+/**
+ * @brief Function for returning the address of a specific timer task.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] timer_task Timer task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_task_t timer_task);
+
+/**
+ * @brief Function for returning the address of a specific timer capture task.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel Capture channel number.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * const p_instance,
+ uint32_t channel);
+
+/**
+ * @brief Function for returning the address of a specific timer event.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] timer_event Timer event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_event_t timer_event);
+
+/**
+ * @brief Function for returning the address of a specific timer compare event.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel Compare channel number.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * const p_instance,
+ uint32_t channel);
+
+/**
+ * @brief Function for capturing the timer value.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] cc_channel Capture channel number.
+ *
+ * @return Captured value.
+ */
+uint32_t nrfx_timer_capture(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel);
+
+/**
+ * @brief Function for returning the capture value from a specific channel.
+ *
+ * Use this function to read channel values when PPI is used for capturing.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] cc_channel Capture channel number.
+ *
+ * @return Captured value.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel);
+
+/**
+ * @brief Function for setting the timer channel in compare mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] cc_channel Compare channel number.
+ * @param[in] cc_value Compare value.
+ * @param[in] enable_int Enable or disable the interrupt for the compare channel.
+ */
+void nrfx_timer_compare(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel,
+ uint32_t cc_value,
+ bool enable_int);
+
+/**
+ * @brief Function for setting the timer channel in extended compare mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] cc_channel Compare channel number.
+ * @param[in] cc_value Compare value.
+ * @param[in] timer_short_mask Shortcut between the compare event on the channel
+ * and the timer task (STOP or CLEAR).
+ * @param[in] enable_int Enable or disable the interrupt for the compare
+ * channel.
+ */
+void nrfx_timer_extended_compare(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel,
+ uint32_t cc_value,
+ nrf_timer_short_mask_t timer_short_mask,
+ bool enable_int);
+
+/**
+ * @brief Function for converting time in microseconds to timer ticks.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] time_us Time in microseconds.
+ *
+ * @return Number of ticks.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_us_to_ticks(nrfx_timer_t const * const p_instance,
+ uint32_t time_us);
+
+/**
+ * @brief Function for converting time in milliseconds to timer ticks.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] time_ms Time in milliseconds.
+ *
+ * @return Number of ticks.
+ */
+__STATIC_INLINE uint32_t nrfx_timer_ms_to_ticks(nrfx_timer_t const * const p_instance,
+ uint32_t time_ms);
+
+/**
+ * @brief Function for enabling timer compare interrupt.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel Compare channel.
+ */
+void nrfx_timer_compare_int_enable(nrfx_timer_t const * const p_instance,
+ uint32_t channel);
+
+/**
+ * @brief Function for disabling timer compare interrupt.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] channel Compare channel.
+ */
+void nrfx_timer_compare_int_disable(nrfx_timer_t const * const p_instance,
+ uint32_t channel);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_task_t timer_task)
+{
+ return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg, timer_task);
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * const p_instance,
+ uint32_t channel)
+{
+ NRFX_ASSERT(channel < p_instance->cc_channel_count);
+ return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg,
+ nrf_timer_capture_task_get(channel));
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_event_t timer_event)
+{
+ return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg, timer_event);
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * const p_instance,
+ uint32_t channel)
+{
+ NRFX_ASSERT(channel < p_instance->cc_channel_count);
+ return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg,
+ nrf_timer_compare_event_get(channel));
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel)
+{
+ return nrf_timer_cc_read(p_instance->p_reg, cc_channel);
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_us_to_ticks(nrfx_timer_t const * const p_instance,
+ uint32_t timer_us)
+{
+ return nrf_timer_us_to_ticks(timer_us, nrf_timer_frequency_get(p_instance->p_reg));
+}
+
+__STATIC_INLINE uint32_t nrfx_timer_ms_to_ticks(nrfx_timer_t const * const p_instance,
+ uint32_t timer_ms)
+{
+ return nrf_timer_ms_to_ticks(timer_ms, nrf_timer_frequency_get(p_instance->p_reg));
+}
+
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_timer_0_irq_handler(void);
+void nrfx_timer_1_irq_handler(void);
+void nrfx_timer_2_irq_handler(void);
+void nrfx_timer_3_irq_handler(void);
+void nrfx_timer_4_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_TIMER_H__
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twi.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twi.h
new file mode 100644
index 0000000..c5b8590
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twi.h
@@ -0,0 +1,368 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_TWI_H__
+#define NRFX_TWI_H__
+
+#include <nrfx.h>
+#include <hal/nrf_twi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_twi TWI driver
+ * @{
+ * @ingroup nrf_twi
+ * @brief TWI peripheral driver.
+ */
+
+/**
+ * @brief Structure for the TWI master driver instance.
+ */
+typedef struct
+{
+ NRF_TWI_Type * p_twi; ///< Pointer to a structure with TWI registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_twi_t;
+
+/**
+ * @brief Macro for creating a TWI master driver instance.
+ */
+#define NRFX_TWI_INSTANCE(id) \
+{ \
+ .p_twi = NRFX_CONCAT_2(NRF_TWI, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_TWI, id, _INST_IDX), \
+}
+
+enum {
+#if NRFX_CHECK(NRFX_TWI0_ENABLED)
+ NRFX_TWI0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TWI1_ENABLED)
+ NRFX_TWI1_INST_IDX,
+#endif
+ NRFX_TWI_ENABLED_COUNT
+};
+
+/**
+ * @brief Structure for the TWI master driver instance configuration.
+ */
+typedef struct
+{
+ uint32_t scl; ///< SCL pin number.
+ uint32_t sda; ///< SDA pin number.
+ nrf_twi_frequency_t frequency; ///< TWI frequency.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+ bool hold_bus_uninit; ///< Hold pull up state on gpio pins after uninit.
+} nrfx_twi_config_t;
+
+/**
+ * @brief TWI master driver instance default configuration.
+ */
+#define NRFX_TWI_DEFAULT_CONFIG \
+{ \
+ .frequency = (nrf_twi_frequency_t)NRFX_TWI_DEFAULT_CONFIG_FREQUENCY, \
+ .scl = 31, \
+ .sda = 31, \
+ .interrupt_priority = NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .hold_bus_uninit = NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \
+}
+
+#define NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */
+#define NRFX_TWI_FLAG_TX_NO_STOP (1UL << 5) /**< Flag indicating that the TX transfer will not end with a stop condition. */
+
+/**
+ * @brief TWI master driver event types.
+ */
+typedef enum
+{
+ NRFX_TWI_EVT_DONE, ///< Transfer completed event.
+ NRFX_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
+ NRFX_TWI_EVT_DATA_NACK ///< Error event: NACK received after sending a data byte.
+} nrfx_twi_evt_type_t;
+
+/**
+ * @brief TWI master driver transfer types.
+ */
+typedef enum
+{
+ NRFX_TWI_XFER_TX, ///< TX transfer.
+ NRFX_TWI_XFER_RX, ///< RX transfer.
+ NRFX_TWI_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start.
+ NRFX_TWI_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start.
+} nrfx_twi_xfer_type_t;
+
+/**
+ * @brief Structure for a TWI transfer descriptor.
+ */
+typedef struct
+{
+ nrfx_twi_xfer_type_t type; ///< Type of transfer.
+ uint8_t address; ///< Slave address.
+ size_t primary_length; ///< Number of bytes transferred.
+ size_t secondary_length; ///< Number of bytes transferred.
+ uint8_t * p_primary_buf; ///< Pointer to transferred data.
+ uint8_t * p_secondary_buf; ///< Pointer to transferred data.
+} nrfx_twi_xfer_desc_t;
+
+
+/**@brief Macro for setting the TX transfer descriptor. */
+#define NRFX_TWI_XFER_DESC_TX(addr, p_data, length) \
+ { \
+ .type = NRFX_TWI_XFER_TX, \
+ .address = addr, \
+ .primary_length = length, \
+ .p_primary_buf = p_data, \
+ }
+
+/**@brief Macro for setting the RX transfer descriptor. */
+#define NRFX_TWI_XFER_DESC_RX(addr, p_data, length) \
+ { \
+ .type = NRFX_TWI_XFER_RX, \
+ .address = addr, \
+ .primary_length = length, \
+ .p_primary_buf = p_data, \
+ }
+
+/**@brief Macro for setting the TXRX transfer descriptor. */
+#define NRFX_TWI_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \
+ { \
+ .type = NRFX_TWI_XFER_TXRX, \
+ .address = addr, \
+ .primary_length = tx_len, \
+ .secondary_length = rx_len, \
+ .p_primary_buf = p_tx, \
+ .p_secondary_buf = p_rx, \
+ }
+
+/**@brief Macro for setting the TXTX transfer descriptor. */
+#define NRFX_TWI_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \
+ { \
+ .type = NRFX_TWI_XFER_TXTX, \
+ .address = addr, \
+ .primary_length = tx_len, \
+ .secondary_length = tx_len2, \
+ .p_primary_buf = p_tx, \
+ .p_secondary_buf = p_tx2, \
+ }
+
+/**
+ * @brief Structure for a TWI event.
+ */
+typedef struct
+{
+ nrfx_twi_evt_type_t type; ///< Event type.
+ nrfx_twi_xfer_desc_t xfer_desc; ///< Transfer details.
+} nrfx_twi_evt_t;
+
+/**
+ * @brief TWI event handler prototype.
+ */
+typedef void (* nrfx_twi_evt_handler_t)(nrfx_twi_evt_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the TWI driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled.
+ * @param[in] p_context Context passed to event handler.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is in invalid state.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_twi_init(nrfx_twi_t const * p_instance,
+ nrfx_twi_config_t const * p_config,
+ nrfx_twi_evt_handler_t event_handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twi_uninit(nrfx_twi_t const * p_instance);
+
+/**
+ * @brief Function for enabling the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twi_enable(nrfx_twi_t const * p_instance);
+
+/**
+ * @brief Function for disabling the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twi_disable(nrfx_twi_t const * p_instance);
+
+/**
+ * @brief Function for sending data to a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRFX_ERROR_BUSY.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] address Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data Pointer to a transmit buffer.
+ * @param[in] length Number of bytes to send.
+ * @param[in] no_stop If set, the stop condition is not generated on the bus
+ * after the transfer has completed successfully (allowing
+ * for a repeated start in the next transfer).
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode.
+ */
+nrfx_err_t nrfx_twi_tx(nrfx_twi_t const * p_instance,
+ uint8_t address,
+ uint8_t const * p_data,
+ size_t length,
+ bool no_stop);
+
+/**
+ * @brief Function for reading data from a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRFX_ERROR_BUSY.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] address Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data Pointer to a receive buffer.
+ * @param[in] length Number of bytes to be received.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode.
+ */
+nrfx_err_t nrfx_twi_rx(nrfx_twi_t const * p_instance,
+ uint8_t address,
+ uint8_t * p_data,
+ size_t length);
+
+/**
+ * @brief Function for preparing a TWI transfer.
+ *
+ * The following transfer types can be configured (@ref nrfx_twi_xfer_desc_t::type):
+ * - @ref NRFX_TWI_XFER_TXRX<span></span>: Write operation followed by a read operation (without STOP condition in between).
+ * - @ref NRFX_TWI_XFER_TXTX<span></span>: Write operation followed by a write operation (without STOP condition in between).
+ * - @ref NRFX_TWI_XFER_TX<span></span>: Write operation (with or without STOP condition).
+ * - @ref NRFX_TWI_XFER_RX<span></span>: Read operation (with STOP condition).
+ *
+ * @note TXRX and TXTX transfers are supported only in non-blocking mode.
+ *
+ * Additional options are provided using the flags parameter:
+ * - @ref NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER<span></span>: No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer.
+ * - @ref NRFX_TWI_FLAG_TX_NO_STOP<span></span>: No stop condition after TX transfer.
+ *
+ * @note
+ * Some flag combinations are invalid:
+ * - @ref NRFX_TWI_FLAG_TX_NO_STOP with @ref nrfx_twi_xfer_desc_t::type different than @ref NRFX_TWI_XFER_TX
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_xfer_desc Pointer to the transfer descriptor.
+ * @param[in] flags Transfer options (0 for default settings).
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data (TXRX and RX)
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte.
+ */
+nrfx_err_t nrfx_twi_xfer(nrfx_twi_t const * p_instance,
+ nrfx_twi_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags);
+
+/**
+ * @brief Function for checking the TWI driver state.
+ *
+ * @param[in] p_instance TWI instance.
+ *
+ * @retval true If the TWI driver is currently busy performing a transfer.
+ * @retval false If the TWI driver is ready for a new transfer.
+ */
+bool nrfx_twi_is_busy(nrfx_twi_t const * p_instance);
+
+/**
+ * @brief Function for getting the transferred data count.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return Data count.
+ */
+size_t nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance);
+
+/**
+ * @brief Function for returning the address of a STOPPED TWI event.
+ *
+ * A STOPPED event can be used to detect the end of a transfer if the @ref NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER
+ * option is used.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return STOPPED event address.
+ */
+uint32_t nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance);
+
+void nrfx_twi_0_irq_handler(void);
+void nrfx_twi_1_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_TWI_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twim.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twim.h
new file mode 100644
index 0000000..0b1be22
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twim.h
@@ -0,0 +1,408 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_TWIM_H__
+#define NRFX_TWIM_H__
+
+#include <nrfx.h>
+#include <hal/nrf_twim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_twim TWIM driver
+ * @{
+ * @ingroup nrf_twim
+ * @brief TWIM peripheral driver.
+ */
+
+/**
+ * @brief Structure for the TWI master driver instance.
+ */
+typedef struct
+{
+ NRF_TWIM_Type * p_twim; ///< Pointer to a structure with TWIM registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_twim_t;
+
+/**
+ * @brief Macro for creating a TWI master driver instance.
+ */
+#define NRFX_TWIM_INSTANCE(id) \
+{ \
+ .p_twim = NRFX_CONCAT_2(NRF_TWIM, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIM, id, _INST_IDX), \
+}
+
+enum {
+#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
+ NRFX_TWIM0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
+ NRFX_TWIM1_INST_IDX,
+#endif
+ NRFX_TWIM_ENABLED_COUNT
+};
+
+/**
+ * @brief Structure for the TWI master driver instance configuration.
+ */
+typedef struct
+{
+ uint32_t scl; ///< SCL pin number.
+ uint32_t sda; ///< SDA pin number.
+ nrf_twim_frequency_t frequency; ///< TWIM frequency.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+ bool hold_bus_uninit; ///< Hold pull up state on gpio pins after uninit.
+} nrfx_twim_config_t;
+
+/**
+ * @brief TWI master driver instance default configuration.
+ */
+#define NRFX_TWIM_DEFAULT_CONFIG \
+{ \
+ .frequency = (nrf_twim_frequency_t)NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY, \
+ .scl = 31, \
+ .sda = 31, \
+ .interrupt_priority = NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
+ .hold_bus_uninit = NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \
+}
+
+#define NRFX_TWIM_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */
+#define NRFX_TWIM_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */
+#define NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */
+#define NRFX_TWIM_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */
+#define NRFX_TWIM_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */
+#define NRFX_TWIM_FLAG_TX_NO_STOP (1UL << 5) /**< Flag indicating that the TX transfer will not end with a stop condition. */
+
+/**
+ * @brief TWI master driver event types.
+ */
+typedef enum
+{
+ NRFX_TWIM_EVT_DONE, ///< Transfer completed event.
+ NRFX_TWIM_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
+ NRFX_TWIM_EVT_DATA_NACK ///< Error event: NACK received after sending a data byte.
+} nrfx_twim_evt_type_t;
+
+/**
+ * @brief TWI master driver transfer types.
+ */
+typedef enum
+{
+ NRFX_TWIM_XFER_TX, ///< TX transfer.
+ NRFX_TWIM_XFER_RX, ///< RX transfer.
+ NRFX_TWIM_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start.
+ NRFX_TWIM_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start.
+} nrfx_twim_xfer_type_t;
+
+/**
+ * @brief Structure for a TWI transfer descriptor.
+ */
+typedef struct
+{
+ nrfx_twim_xfer_type_t type; ///< Type of transfer.
+ uint8_t address; ///< Slave address.
+ size_t primary_length; ///< Number of bytes transferred.
+ size_t secondary_length; ///< Number of bytes transferred.
+ uint8_t * p_primary_buf; ///< Pointer to transferred data.
+ uint8_t * p_secondary_buf; ///< Pointer to transferred data.
+} nrfx_twim_xfer_desc_t;
+
+
+/**@brief Macro for setting the TX transfer descriptor. */
+#define NRFX_TWIM_XFER_DESC_TX(addr, p_data, length) \
+ { \
+ .type = NRFX_TWIM_XFER_TX, \
+ .address = addr, \
+ .primary_length = length, \
+ .p_primary_buf = p_data, \
+ }
+
+/**@brief Macro for setting the RX transfer descriptor. */
+#define NRFX_TWIM_XFER_DESC_RX(addr, p_data, length) \
+ { \
+ .type = NRFX_TWIM_XFER_RX, \
+ .address = addr, \
+ .primary_length = length, \
+ .p_primary_buf = p_data, \
+ }
+
+/**@brief Macro for setting the TXRX transfer descriptor. */
+#define NRFX_TWIM_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \
+ { \
+ .type = NRFX_TWIM_XFER_TXRX, \
+ .address = addr, \
+ .primary_length = tx_len, \
+ .secondary_length = rx_len, \
+ .p_primary_buf = p_tx, \
+ .p_secondary_buf = p_rx, \
+ }
+
+/**@brief Macro for setting the TXTX transfer descriptor. */
+#define NRFX_TWIM_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \
+ { \
+ .type = NRFX_TWIM_XFER_TXTX, \
+ .address = addr, \
+ .primary_length = tx_len, \
+ .secondary_length = tx_len2, \
+ .p_primary_buf = p_tx, \
+ .p_secondary_buf = p_tx2, \
+ }
+
+/**
+ * @brief Structure for a TWI event.
+ */
+typedef struct
+{
+ nrfx_twim_evt_type_t type; ///< Event type.
+ nrfx_twim_xfer_desc_t xfer_desc; ///< Transfer details.
+} nrfx_twim_evt_t;
+
+/**
+ * @brief TWI event handler prototype.
+ */
+typedef void (* nrfx_twim_evt_handler_t)(nrfx_twim_evt_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the TWI driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled.
+ * @param[in] p_context Context passed to event handler.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is in invalid state.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
+ nrfx_twim_config_t const * p_config,
+ nrfx_twim_evt_handler_t event_handler,
+ void * p_context);
+
+/**
+ * @brief Function for uninitializing the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twim_uninit(nrfx_twim_t const * p_instance);
+
+/**
+ * @brief Function for enabling the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twim_enable(nrfx_twim_t const * p_instance);
+
+/**
+ * @brief Function for disabling the TWI instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twim_disable(nrfx_twim_t const * p_instance);
+
+/**
+ * @brief Function for sending data to a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRFX_ERROR_BUSY.
+ *
+ * @note Peripherals using EasyDMA (including TWIM) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] address Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data Pointer to a transmit buffer.
+ * @param[in] length Number of bytes to send. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The driver
+ * checks it with assertion.
+ * @param[in] no_stop If set, the stop condition is not generated on the bus
+ * after the transfer has completed successfully (allowing
+ * for a repeated start in the next transfer).
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffer is not placed in the Data RAM region.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode.
+ */
+nrfx_err_t nrfx_twim_tx(nrfx_twim_t const * p_instance,
+ uint8_t address,
+ uint8_t const * p_data,
+ size_t length,
+ bool no_stop);
+
+/**
+ * @brief Function for reading data from a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRFX_ERROR_BUSY.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] address Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data Pointer to a receive buffer.
+ * @param[in] length Number of bytes to be received. Maximum possible length
+ * is dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The driver
+ * checks it with assertion.
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode.
+ */
+nrfx_err_t nrfx_twim_rx(nrfx_twim_t const * p_instance,
+ uint8_t address,
+ uint8_t * p_data,
+ size_t length);
+
+/**
+ * @brief Function for preparing a TWI transfer.
+ *
+ * The following transfer types can be configured (@ref nrfx_twim_xfer_desc_t::type):
+ * - @ref NRFX_TWIM_XFER_TXRX<span></span>: Write operation followed by a read operation (without STOP condition in between).
+ * - @ref NRFX_TWIM_XFER_TXTX<span></span>: Write operation followed by a write operation (without STOP condition in between).
+ * - @ref NRFX_TWIM_XFER_TX<span></span>: Write operation (with or without STOP condition).
+ * - @ref NRFX_TWIM_XFER_RX<span></span>: Read operation (with STOP condition).
+ *
+ * @note TXRX and TXTX transfers are supported only in non-blocking mode.
+ *
+ * Additional options are provided using the flags parameter:
+ * - @ref NRFX_TWIM_FLAG_TX_POSTINC and @ref NRFX_TWIM_FLAG_RX_POSTINC<span></span>: Post-incrementation of buffer addresses. Supported only by TWIM.
+ * - @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER<span></span>: No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer.
+ * - @ref NRFX_TWIM_FLAG_HOLD_XFER<span></span>: Driver is not starting the transfer. Use this flag if the transfer is triggered externally by PPI. Supported only by TWIM.
+ * Use @ref nrfx_twim_start_task_get to get the address of the start task.
+ * - @ref NRFX_TWIM_FLAG_REPEATED_XFER<span></span>: Prepare for repeated transfers. You can set up a number of transfers that will be triggered externally (for example by PPI).
+ * An example is a TXRX transfer with the options @ref NRFX_TWIM_FLAG_RX_POSTINC, @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_TWIM_FLAG_REPEATED_XFER.
+ * After the transfer is set up, a set of transfers can be triggered by PPI that will read, for example, the same register of an
+ * external component and put it into a RAM buffer without any interrupts. @ref nrfx_twim_stopped_event_get can be used to get the
+ * address of the STOPPED event, which can be used to count the number of transfers. If @ref NRFX_TWIM_FLAG_REPEATED_XFER is used,
+ * the driver does not set the driver instance into busy state, so you must ensure that the next transfers are set up
+ * when TWIM is not active. Supported only by TWIM.
+ * - @ref NRFX_TWIM_FLAG_TX_NO_STOP<span></span>: No stop condition after TX transfer.
+ *
+ * @note
+ * Some flag combinations are invalid:
+ * - @ref NRFX_TWIM_FLAG_TX_NO_STOP with @ref nrfx_twim_xfer_desc_t::type different than @ref NRFX_TWIM_XFER_TX
+ * - @ref NRFX_TWIM_FLAG_REPEATED_XFER with @ref nrfx_twim_xfer_desc_t::type set to @ref NRFX_TWIM_XFER_TXTX
+ *
+ * If @ref nrfx_twim_xfer_desc_t::type is set to @ref NRFX_TWIM_XFER_TX and the @ref NRFX_TWIM_FLAG_TX_NO_STOP and @ref NRFX_TWIM_FLAG_REPEATED_XFER
+ * flags are set, two tasks must be used to trigger a transfer: TASKS_RESUME followed by TASKS_STARTTX. If no stop condition is generated,
+ * TWIM is in SUSPENDED state. Therefore, it must be resumed before the transfer can be started.
+ *
+ * @note Peripherals using EasyDMA (including TWIM) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_xfer_desc Pointer to the transfer descriptor.
+ * @param[in] flags Transfer options (0 for default settings).
+ *
+ * @retval NRFX_SUCCESS If the procedure was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ * @retval NRFX_ERROR_INTERNAL If an error was detected by hardware.
+ * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data RAM region.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address.
+ * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte.
+ */
+nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
+ nrfx_twim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags);
+
+/**
+ * @brief Function for checking the TWI driver state.
+ *
+ * @param[in] p_instance TWI instance.
+ *
+ * @retval true If the TWI driver is currently busy performing a transfer.
+ * @retval false If the TWI driver is ready for a new transfer.
+ */
+bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance);
+
+
+/**
+ * @brief Function for returning the address of a TWIM start task.
+ *
+ * This function should be used if @ref nrfx_twim_xfer was called with the flag @ref NRFX_TWIM_FLAG_HOLD_XFER.
+ * In that case, the transfer is not started by the driver, but it must be started externally by PPI.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] xfer_type Transfer type used in the last call of the @ref nrfx_twim_xfer function.
+ *
+ * @return Start task address (TX or RX) depending on the value of xfer_type.
+ */
+uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance, nrfx_twim_xfer_type_t xfer_type);
+
+/**
+ * @brief Function for returning the address of a STOPPED TWIM event.
+ *
+ * A STOPPED event can be used to detect the end of a transfer if the @ref NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER
+ * option is used.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return STOPPED event address.
+ */
+uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance);
+
+
+void nrfx_twim_0_irq_handler(void);
+void nrfx_twim_1_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_TWIM_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twis.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twis.h
new file mode 100644
index 0000000..5630868
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_twis.h
@@ -0,0 +1,405 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_TWIS_H__
+#define NRFX_TWIS_H__
+
+#include <nrfx.h>
+#include <hal/nrf_twis.h>
+#include <hal/nrf_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_twis TWIS driver
+ * @{
+ * @ingroup nrf_twis
+ * @brief Two Wire Slave interface (TWIS) peripheral driver.
+ */
+
+/**
+ * @brief TWIS driver instance data structure.
+ */
+typedef struct
+{
+ NRF_TWIS_Type * p_reg; ///< Pointer to a structure with TWIS registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_twis_t;
+
+enum {
+#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
+ NRFX_TWIS0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
+ NRFX_TWIS1_INST_IDX,
+#endif
+ NRFX_TWIS_ENABLED_COUNT
+};
+
+/**
+ * @brief Macro for creating a TWIS driver instance.
+ */
+#define NRFX_TWIS_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_TWIS, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIS, id, _INST_IDX), \
+}
+
+/**
+ * @brief Event callback function event definitions.
+ */
+typedef enum
+{
+ NRFX_TWIS_EVT_READ_REQ, ///< Read request detected.
+ /**< If there is no buffer prepared, buf_req flag in the even will be set.
+ Call then @ref nrfx_twis_tx_prepare to give parameters for buffer.
+ */
+ NRFX_TWIS_EVT_READ_DONE, ///< Read request has finished - free any data.
+ NRFX_TWIS_EVT_READ_ERROR, ///< Read request finished with error.
+ NRFX_TWIS_EVT_WRITE_REQ, ///< Write request detected.
+ /**< If there is no buffer prepared, buf_req flag in the even will be set.
+ Call then @ref nrfx_twis_rx_prepare to give parameters for buffer.
+ */
+ NRFX_TWIS_EVT_WRITE_DONE, ///< Write request has finished - process data.
+ NRFX_TWIS_EVT_WRITE_ERROR, ///< Write request finished with error.
+ NRFX_TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction.
+} nrfx_twis_evt_type_t;
+
+/**
+ * @brief Possible error sources.
+ *
+ * This is flag enum - values from this enum can be connected using logical or operator.
+ * @note
+ * We could use directly @ref nrf_twis_error_t. Error type enum is redefined here because
+ * of possible future extension (eg. supporting timeouts and synchronous mode).
+ */
+typedef enum
+{
+ NRFX_TWIS_ERROR_OVERFLOW = NRF_TWIS_ERROR_OVERFLOW, /**< RX buffer overflow detected, and prevented. */
+ NRFX_TWIS_ERROR_DATA_NACK = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte. */
+ NRFX_TWIS_ERROR_OVERREAD = NRF_TWIS_ERROR_OVERREAD, /**< TX buffer over-read detected, and prevented. */
+ NRFX_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8 /**< Unexpected event detected by state machine. */
+} nrfx_twis_error_t;
+
+/**
+ * @brief TWIS driver event structure.
+ */
+typedef struct
+{
+ nrfx_twis_evt_type_t type; ///< Event type.
+ union
+ {
+ bool buf_req; ///< Flag for @ref NRFX_TWIS_EVT_READ_REQ and @ref NRFX_TWIS_EVT_WRITE_REQ.
+ /**< Information if transmission buffer requires to be prepared. */
+ uint32_t tx_amount; ///< Data for @ref NRFX_TWIS_EVT_READ_DONE.
+ uint32_t rx_amount; ///< Data for @ref NRFX_TWIS_EVT_WRITE_DONE.
+ uint32_t error; ///< Data for @ref NRFX_TWIS_EVT_GENERAL_ERROR.
+ } data;
+} nrfx_twis_evt_t;
+
+/**
+ * @brief TWI slave event callback function type.
+ *
+ * @param[in] p_event Event information structure.
+ */
+typedef void (*nrfx_twis_event_handler_t)(nrfx_twis_evt_t const * p_event);
+
+/**
+ * @brief Structure for TWIS configuration.
+ */
+typedef struct
+{
+ uint32_t addr[2]; //!< Set addresses that this slave should respond. Set 0 to disable.
+ uint32_t scl; //!< SCL pin number.
+ uint32_t sda; //!< SDA pin number.
+ nrf_gpio_pin_pull_t scl_pull; //!< SCL pin pull.
+ nrf_gpio_pin_pull_t sda_pull; //!< SDA pin pull.
+ uint8_t interrupt_priority; //!< The priority of interrupt for the module to set.
+} nrfx_twis_config_t;
+
+/**
+ * @brief Generate default configuration for TWIS driver instance.
+ */
+#define NRFX_TWIS_DEFAULT_CONFIG \
+{ \
+ .addr = { NRFX_TWIS_DEFAULT_CONFIG_ADDR0, \
+ NRFX_TWIS_DEFAULT_CONFIG_ADDR1 }, \
+ .scl = 31, \
+ .scl_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL, \
+ .sda = 31, \
+ .sda_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL, \
+ .interrupt_priority = NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY \
+}
+
+/**
+ * @brief Function for initializing the TWIS driver instance.
+ *
+ * Function initializes and enables TWIS driver.
+ * @attention After driver initialization enable it by @ref nrfx_twis_enable.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @attention @em p_instance has to be global object.
+ * It would be used by interrupts so make it sure that object
+ * would not be destroyed when function is leaving.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If the driver is already initialized.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if NRFX_PRS_ENABLED
+ * is set to a value other than zero.
+ */
+nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
+ nrfx_twis_config_t const * p_config,
+ nrfx_twis_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the TWIS driver instance.
+ *
+ * Function initializes the peripheral and resets all registers to default values.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @note
+ * It is safe to call nrfx_twis_uninit even before initialization.
+ * Actually @ref nrfx_twis_init function calls this function to
+ * make sure that TWIS state is known.
+ * @note
+ * If TWIS driver was in uninitialized state before calling this function,
+ * selected pins would not be reset to default configuration.
+ */
+void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Enable TWIS instance.
+ *
+ * This function enables TWIS instance.
+ * Function defined if there is needs for dynamically enabling and disabling the peripheral.
+ * Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
+ * They do not change any configuration registers.
+ *
+ * @param p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twis_enable(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Disable TWIS instance.
+ *
+ * Disabling TWIS instance gives possibility to turn off the TWIS while
+ * holding configuration done by @ref nrfx_twis_init.
+ *
+ * @param p_instance Pointer to the driver instance structure.
+ */
+void nrfx_twis_disable(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Get and clear last error flags.
+ *
+ * Function gets information about errors.
+ * This is also the only possibility to exit from error substate of the internal state machine.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @return Error flags defined in @ref nrfx_twis_error_t.
+ * @attention
+ * This function clears error state and flags.
+ */
+uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
+
+
+/**
+ * @brief Prepare data for sending.
+ *
+ * This function should be used in response for @ref NRFX_TWIS_EVT_READ_REQ event.
+ *
+ * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_buf Transmission buffer.
+ * @attention Transmission buffer has to be placed in RAM.
+ * @param size Maximum number of bytes that master may read from buffer given.
+ *
+ * @retval NRFX_SUCCESS Preparation finished properly.
+ * @retval NRFX_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM.
+ * @retval NRFX_ERROR_INVALID_LENGTH Wrong value in @em size parameter.
+ * @retval NRFX_ERROR_INVALID_STATE Module not initialized or not enabled.
+ */
+nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
+ void const * p_buf,
+ size_t size);
+
+/**
+ * @brief Get number of transmitted bytes.
+ *
+ * Function returns number of bytes sent.
+ * This function may be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return Number of bytes sent.
+ */
+__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Prepare data for receiving
+ *
+ * This function should be used in response for @ref NRFX_TWIS_EVT_WRITE_REQ event.
+ *
+ * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_buf Buffer that would be filled with received data.
+ * @attention Receiving buffer has to be placed in RAM.
+ * @param size Size of the buffer (maximum amount of data to receive).
+ *
+ * @retval NRFX_SUCCESS Preparation finished properly.
+ * @retval NRFX_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM.
+ * @retval NRFX_ERROR_INVALID_LENGTH Wrong value in @em size parameter.
+ * @retval NRFX_ERROR_INVALID_STATE Module not initialized or not enabled.
+ */
+nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
+ void * p_buf,
+ size_t size);
+
+/**
+ * @brief Get number of received bytes.
+ *
+ * Function returns number of bytes received.
+ * This function may be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return Number of bytes received.
+ */
+__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Function checks if driver is busy right now.
+ *
+ * Actual driver substate is tested.
+ * If driver is in any other state than IDLE or ERROR this function returns true.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true Driver is in state other than ERROR or IDLE.
+ * @retval false There is no transmission pending.
+ */
+bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Function checks if driver is waiting for tx buffer.
+ *
+ * If this function returns true, it means that driver is stalled expecting
+ * of the @ref nrfx_twis_tx_prepare function call.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true Driver waits for @ref nrfx_twis_tx_prepare.
+ * @retval false Driver is not in the state where it waits for preparing tx buffer.
+ */
+bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Function checks if driver is waiting for rx buffer.
+ *
+ * If this function returns true, it means that driver is staled expecting
+ * of the @ref nrfx_twis_rx_prepare function call.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true Driver waits for @ref nrfx_twis_rx_prepare.
+ * @retval false Driver is not in the state where it waits for preparing rx buffer.
+ */
+bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Check if driver is sending data.
+ *
+ * If this function returns true, it means that there is ongoing output transmission.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true There is ongoing output transmission.
+ * @retval false Driver is in other state.
+ */
+bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
+
+/**
+ * @brief Check if driver is receiving data.
+ *
+ * If this function returns true, it means that there is ongoing input transmission.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true There is ongoing input transmission.
+ * @retval false Driver is in other state.
+ */
+bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
+{
+ return nrf_twis_tx_amount_get(p_instance->p_reg);
+}
+
+__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
+{
+ return nrf_twis_rx_amount_get(p_instance->p_reg);
+}
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_twis_0_irq_handler(void);
+void nrfx_twis_1_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_TWIS_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uart.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uart.h
new file mode 100644
index 0000000..d55beb7
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uart.h
@@ -0,0 +1,365 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_UART_H__
+#define NRFX_UART_H__
+
+#include <nrfx.h>
+#include <hal/nrf_uart.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_uart UART driver
+ * @{
+ * @ingroup nrf_uart
+ * @brief UART peripheral driver.
+ */
+
+/**
+ * @brief UART driver instance data structure.
+ */
+typedef struct
+{
+ NRF_UART_Type * p_reg; ///< Pointer to a structure with UART registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_uart_t;
+
+enum {
+#if NRFX_CHECK(NRFX_UART0_ENABLED)
+ NRFX_UART0_INST_IDX,
+#endif
+ NRFX_UART_ENABLED_COUNT
+};
+
+/**
+ * @brief Macro for creating a UART driver instance.
+ */
+#define NRFX_UART_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_UART, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_UART, id, _INST_IDX), \
+}
+
+/**
+ * @brief Types of UART driver events.
+ */
+typedef enum
+{
+ NRFX_UART_EVT_TX_DONE, ///< Requested TX transfer completed.
+ NRFX_UART_EVT_RX_DONE, ///< Requested RX transfer completed.
+ NRFX_UART_EVT_ERROR, ///< Error reported by UART peripheral.
+} nrfx_uart_evt_type_t;
+
+/**
+ * @brief Structure for UART configuration.
+ */
+typedef struct
+{
+ uint32_t pseltxd; ///< TXD pin number.
+ uint32_t pselrxd; ///< RXD pin number.
+ uint32_t pselcts; ///< CTS pin number.
+ uint32_t pselrts; ///< RTS pin number.
+ void * p_context; ///< Context passed to interrupt handler.
+ nrf_uart_hwfc_t hwfc; ///< Flow control configuration.
+ nrf_uart_parity_t parity; ///< Parity configuration.
+ nrf_uart_baudrate_t baudrate; ///< Baudrate.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+} nrfx_uart_config_t;
+
+/**
+ * @brief UART default configuration.
+ */
+#define NRFX_UART_DEFAULT_CONFIG \
+{ \
+ .pseltxd = NRF_UART_PSEL_DISCONNECTED, \
+ .pselrxd = NRF_UART_PSEL_DISCONNECTED, \
+ .pselcts = NRF_UART_PSEL_DISCONNECTED, \
+ .pselrts = NRF_UART_PSEL_DISCONNECTED, \
+ .p_context = NULL, \
+ .hwfc = (nrf_uart_hwfc_t)NRFX_UART_DEFAULT_CONFIG_HWFC, \
+ .parity = (nrf_uart_parity_t)NRFX_UART_DEFAULT_CONFIG_PARITY, \
+ .baudrate = (nrf_uart_baudrate_t)NRFX_UART_DEFAULT_CONFIG_BAUDRATE, \
+ .interrupt_priority = NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY, \
+}
+
+/**
+ * @brief Structure for UART transfer completion event.
+ */
+typedef struct
+{
+ uint8_t * p_data; ///< Pointer to memory used for transfer.
+ uint32_t bytes; ///< Number of bytes transfered.
+} nrfx_uart_xfer_evt_t;
+
+/**
+ * @brief Structure for UART error event.
+ */
+typedef struct
+{
+ nrfx_uart_xfer_evt_t rxtx; ///< Transfer details includes number of bytes transferred.
+ uint32_t error_mask; ///< Mask of error flags that generated the event.
+} nrfx_uart_error_evt_t;
+
+/**
+ * @brief Structure for UART event.
+ */
+typedef struct
+{
+ nrfx_uart_evt_type_t type; ///< Event type.
+ union
+ {
+ nrfx_uart_xfer_evt_t rxtx; ///< Data provided for transfer completion events.
+ nrfx_uart_error_evt_t error; ///< Data provided for error event.
+ } data;
+} nrfx_uart_event_t;
+
+/**
+ * @brief UART interrupt event handler.
+ *
+ * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available
+ * only within the context of the event handler.
+ * @param[in] p_context Context passed to interrupt handler, set on initialization.
+ */
+typedef void (*nrfx_uart_event_handler_t)(nrfx_uart_event_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the UART driver.
+ *
+ * This function configures and enables UART. After this function GPIO pins are controlled by UART.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user. If not provided driver works in
+ * blocking mode.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If driver is already initialized.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_uart_init(nrfx_uart_t const * p_instance,
+ nrfx_uart_config_t const * p_config,
+ nrfx_uart_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the UART driver.
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uart_uninit(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for getting the address of a specific UART task.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] task Task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
+ nrf_uart_task_t task);
+
+/**
+ * @brief Function for getting the address of a specific UART event.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] event Event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
+ nrf_uart_event_t event);
+
+/**
+ * @brief Function for sending data over UART.
+ *
+ * If an event handler was provided in nrfx_uart_init() call, this function
+ * returns immediately and the handler is called when the transfer is done.
+ * Otherwise, the transfer is performed in blocking mode, i.e. this function
+ * returns when the transfer is finished. Blocking mode is not using interrupt
+ * so there is no context switching inside the function.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to send.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_BUSY If driver is already transferring.
+ * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context
+ * (blocking mode only).
+ */
+nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
+ uint8_t const * p_data,
+ size_t length);
+
+/**
+ * @brief Function for checking if UART is currently transmitting.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true If UART is transmitting.
+ * @retval false If UART is not transmitting.
+ */
+bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for aborting any ongoing transmission.
+ * @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
+ * It will contain number of bytes sent until abort was called. The event
+ * handler will be called from the function context.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for receiving data over UART.
+ *
+ * If an event handler was provided in the nrfx_uart_init() call, this function
+ * returns immediately and the handler is called when the transfer is done.
+ * Otherwise, the transfer is performed in blocking mode, i.e. this function
+ * returns when the transfer is finished. Blocking mode is not using interrupt so
+ * there is no context switching inside the function.
+ * The receive buffer pointer is double buffered in non-blocking mode. The secondary
+ * buffer can be set immediately after starting the transfer and will be filled
+ * when the primary buffer is full. The double buffering feature allows
+ * receiving data continuously.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to receive.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is already receiving
+ * (and the secondary buffer has already been set
+ * in non-blocking mode).
+ * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context
+ * (blocking mode only, also see @ref nrfx_uart_rx_disable).
+ * @retval NRFX_ERROR_INTERNAL If UART peripheral reported an error.
+ */
+nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
+ uint8_t * p_data,
+ size_t length);
+
+
+
+/**
+ * @brief Function for testing the receiver state in blocking mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true If the receiver has at least one byte of data to get.
+ * @retval false If the receiver is empty.
+ */
+bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for enabling the receiver.
+ *
+ * UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the
+ * UART receive function before the FIFO is filled, an overrun error will appear. The receiver must be
+ * explicitly closed by the user @sa nrfx_uart_rx_disable.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for disabling the receiver.
+ *
+ * This function must be called to close the receiver after it has been explicitly enabled by
+ * @sa nrfx_uart_rx_enable.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for aborting any ongoing reception.
+ * @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
+ * It will contain number of bytes received until abort was called. The event
+ * handler will be called from the UART interrupt context.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance);
+
+/**
+ * @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t.
+ * @note Function should be used in blocking mode only. In case of non-blocking mode, an error event is
+ * generated. Function clears error sources after reading.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval Mask of reported errors.
+ */
+uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+__STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
+ nrf_uart_task_t task)
+{
+ return nrf_uart_task_address_get(p_instance->p_reg, task);
+}
+
+__STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
+ nrf_uart_event_t event)
+{
+ return nrf_uart_event_address_get(p_instance->p_reg, event);
+}
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_uart_0_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_UART_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uarte.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uarte.h
new file mode 100644
index 0000000..e5deec0
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_uarte.h
@@ -0,0 +1,363 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_UARTE_H__
+#define NRFX_UARTE_H__
+
+#include <nrfx.h>
+#include <hal/nrf_uarte.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_uarte UARTE driver
+ * @{
+ * @ingroup nrf_uarte
+ * @brief UARTE peripheral driver.
+ */
+
+/**
+ * @brief Structure for the UARTE driver instance.
+ */
+typedef struct
+{
+ NRF_UARTE_Type * p_reg; ///< Pointer to a structure with UARTE registers.
+ uint8_t drv_inst_idx; ///< Driver instance index.
+} nrfx_uarte_t;
+
+enum {
+#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
+ NRFX_UARTE0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
+ NRFX_UARTE1_INST_IDX,
+#endif
+ NRFX_UARTE_ENABLED_COUNT
+};
+
+/**
+ * @brief Macro for creating a UARTE driver instance.
+ */
+#define NRFX_UARTE_INSTANCE(id) \
+{ \
+ .p_reg = NRFX_CONCAT_2(NRF_UARTE, id), \
+ .drv_inst_idx = NRFX_CONCAT_3(NRFX_UARTE, id, _INST_IDX), \
+}
+
+/**
+ * @brief Types of UARTE driver events.
+ */
+typedef enum
+{
+ NRFX_UARTE_EVT_TX_DONE, ///< Requested TX transfer completed.
+ NRFX_UARTE_EVT_RX_DONE, ///< Requested RX transfer completed.
+ NRFX_UARTE_EVT_ERROR, ///< Error reported by UART peripheral.
+} nrfx_uarte_evt_type_t;
+
+/**
+ * @brief Structure for UARTE configuration.
+ */
+typedef struct
+{
+ uint32_t pseltxd; ///< TXD pin number.
+ uint32_t pselrxd; ///< RXD pin number.
+ uint32_t pselcts; ///< CTS pin number.
+ uint32_t pselrts; ///< RTS pin number.
+ void * p_context; ///< Context passed to interrupt handler.
+ nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
+ nrf_uarte_parity_t parity; ///< Parity configuration.
+ nrf_uarte_baudrate_t baudrate; ///< Baudrate.
+ uint8_t interrupt_priority; ///< Interrupt priority.
+} nrfx_uarte_config_t;
+
+/**
+ * @brief UARTE default configuration.
+ */
+#define NRFX_UARTE_DEFAULT_CONFIG \
+{ \
+ .pseltxd = NRF_UARTE_PSEL_DISCONNECTED, \
+ .pselrxd = NRF_UARTE_PSEL_DISCONNECTED, \
+ .pselcts = NRF_UARTE_PSEL_DISCONNECTED, \
+ .pselrts = NRF_UARTE_PSEL_DISCONNECTED, \
+ .p_context = NULL, \
+ .hwfc = (nrf_uarte_hwfc_t)NRFX_UARTE_DEFAULT_CONFIG_HWFC, \
+ .parity = (nrf_uarte_parity_t)NRFX_UARTE_DEFAULT_CONFIG_PARITY, \
+ .baudrate = (nrf_uarte_baudrate_t)NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE, \
+ .interrupt_priority = NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY, \
+}
+
+/**
+ * @brief Structure for UARTE transfer completion event.
+ */
+typedef struct
+{
+ uint8_t * p_data; ///< Pointer to memory used for transfer.
+ uint8_t bytes; ///< Number of bytes transfered.
+} nrfx_uarte_xfer_evt_t;
+
+/**
+ * @brief Structure for UARTE error event.
+ */
+typedef struct
+{
+ nrfx_uarte_xfer_evt_t rxtx; ///< Transfer details includes number of bytes transferred.
+ uint32_t error_mask; ///< Mask of error flags that generated the event.
+} nrfx_uarte_error_evt_t;
+
+/**
+ * @brief Structure for UARTE event.
+ */
+typedef struct
+{
+ nrfx_uarte_evt_type_t type; ///< Event type.
+ union
+ {
+ nrfx_uarte_xfer_evt_t rxtx; ///< Data provided for transfer completion events.
+ nrfx_uarte_error_evt_t error; ///< Data provided for error event.
+ } data;
+} nrfx_uarte_event_t;
+
+/**
+ * @brief UARTE interrupt event handler.
+ *
+ * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available
+ * only within the context of the event handler.
+ * @param[in] p_context Context passed to interrupt handler, set on initialization.
+ */
+typedef void (*nrfx_uarte_event_handler_t)(nrfx_uarte_event_t const * p_event,
+ void * p_context);
+
+/**
+ * @brief Function for initializing the UARTE driver.
+ *
+ * This function configures and enables UARTE. After this function GPIO pins are controlled by UARTE.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] event_handler Event handler provided by the user. If not provided driver works in
+ * blocking mode.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE If driver is already initialized.
+ * @retval NRFX_ERROR_BUSY If some other peripheral with the same
+ * instance ID is already in use. This is
+ * possible only if @ref nrfx_prs module
+ * is enabled.
+ */
+nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance,
+ nrfx_uarte_config_t const * p_config,
+ nrfx_uarte_event_handler_t event_handler);
+
+/**
+ * @brief Function for uninitializing the UARTE driver.
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance);
+
+/**
+ * @brief Function for getting the address of a specific UARTE task.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] task Task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_uarte_task_address_get(nrfx_uarte_t const * p_instance,
+ nrf_uarte_task_t task);
+
+/**
+ * @brief Function for getting the address of a specific UARTE event.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] event Event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrfx_uarte_event_address_get(nrfx_uarte_t const * p_instance,
+ nrf_uarte_event_t event);
+
+/**
+ * @brief Function for sending data over UARTE.
+ *
+ * If an event handler was provided in nrfx_uarte_init() call, this function
+ * returns immediately and the handler is called when the transfer is done.
+ * Otherwise, the transfer is performed in blocking mode, i.e. this function
+ * returns when the transfer is finished. Blocking mode is not using interrupt
+ * so there is no context switching inside the function.
+ *
+ * @note Peripherals using EasyDMA (including UARTE) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to send. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The driver
+ * checks it with assertion.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_BUSY If driver is already transferring.
+ * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context
+ * (blocking mode only).
+ * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer.
+ */
+nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
+ uint8_t const * p_data,
+ size_t length);
+
+/**
+ * @brief Function for checking if UARTE is currently transmitting.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true If UARTE is transmitting.
+ * @retval false If UARTE is not transmitting.
+ */
+bool nrfx_uarte_tx_in_progress(nrfx_uarte_t const * p_instance);
+
+/**
+ * @brief Function for aborting any ongoing transmission.
+ * @note @ref NRFX_UARTE_EVT_TX_DONE event will be generated in non-blocking mode.
+ * It will contain number of bytes sent until abort was called. The event
+ * handler will be called from UARTE interrupt context.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uarte_tx_abort(nrfx_uarte_t const * p_instance);
+
+/**
+ * @brief Function for receiving data over UARTE.
+ *
+ * If an event handler was provided in the nrfx_uarte_init() call, this function
+ * returns immediately and the handler is called when the transfer is done.
+ * Otherwise, the transfer is performed in blocking mode, i.e. this function
+ * returns when the transfer is finished. Blocking mode is not using interrupt so
+ * there is no context switching inside the function.
+ * The receive buffer pointer is double buffered in non-blocking mode. The secondary
+ * buffer can be set immediately after starting the transfer and will be filled
+ * when the primary buffer is full. The double buffering feature allows
+ * receiving data continuously.
+ *
+ * @note Peripherals using EasyDMA (including UARTE) require the transfer buffers
+ * to be placed in the Data RAM region. If this condition is not met,
+ * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to receive. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The driver
+ * checks it with assertion.
+ *
+ * @retval NRFX_SUCCESS If initialization was successful.
+ * @retval NRFX_ERROR_BUSY If the driver is already receiving
+ * (and the secondary buffer has already been set
+ * in non-blocking mode).
+ * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context
+ * (blocking mode only).
+ * @retval NRFX_ERROR_INTERNAL If UARTE peripheral reported an error.
+ * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer.
+ */
+nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance,
+ uint8_t * p_data,
+ size_t length);
+
+
+
+/**
+ * @brief Function for testing the receiver state in blocking mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true If the receiver has at least one byte of data to get.
+ * @retval false If the receiver is empty.
+ */
+bool nrfx_uarte_rx_ready(nrfx_uarte_t const * p_instance);
+
+/**
+ * @brief Function for aborting any ongoing reception.
+ * @note @ref NRFX_UARTE_EVT_RX_DONE event will be generated in non-blocking mode.
+ * It will contain number of bytes received until abort was called. The event
+ * handler will be called from UARTE interrupt context.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_uarte_rx_abort(nrfx_uarte_t const * p_instance);
+
+/**
+ * @brief Function for reading error source mask. Mask contains values from @ref nrf_uarte_error_mask_t.
+ * @note Function should be used in blocking mode only. In case of non-blocking mode, an error event is
+ * generated. Function clears error sources after reading.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval Mask of reported errors.
+ */
+uint32_t nrfx_uarte_errorsrc_get(nrfx_uarte_t const * p_instance);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+__STATIC_INLINE uint32_t nrfx_uarte_task_address_get(nrfx_uarte_t const * p_instance,
+ nrf_uarte_task_t task)
+{
+ return nrf_uarte_task_address_get(p_instance->p_reg, task);
+}
+
+__STATIC_INLINE uint32_t nrfx_uarte_event_address_get(nrfx_uarte_t const * p_instance,
+ nrf_uarte_event_t event)
+{
+ return nrf_uarte_event_address_get(p_instance->p_reg, event);
+}
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+
+void nrfx_uarte_0_irq_handler(void);
+void nrfx_uarte_1_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_UARTE_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_wdt.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_wdt.h
new file mode 100644
index 0000000..be98a38
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/include/nrfx_wdt.h
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_WDT_H__
+#define NRFX_WDT_H__
+
+#include <nrfx.h>
+#include <hal/nrf_wdt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_wdt WDT driver
+ * @{
+ * @ingroup nrf_wdt
+ * @brief Watchdog Timer (WDT) peripheral driver.
+ */
+
+/**@brief Struct for WDT initialization. */
+typedef struct
+{
+ nrf_wdt_behaviour_t behaviour; /**< WDT behaviour when CPU in sleep/halt mode. */
+ uint32_t reload_value; /**< WDT reload value in ms. */
+ uint8_t interrupt_priority; /**< WDT interrupt priority */
+} nrfx_wdt_config_t;
+
+/**@brief WDT event handler function type. */
+typedef void (*nrfx_wdt_event_handler_t)(void);
+
+/**@brief WDT channel id type. */
+typedef nrf_wdt_rr_register_t nrfx_wdt_channel_id;
+
+#define NRFX_WDT_DEAFULT_CONFIG \
+ { \
+ .behaviour = (nrf_wdt_behaviour_t)NRFX_WDT_CONFIG_BEHAVIOUR, \
+ .reload_value = NRFX_WDT_CONFIG_RELOAD_VALUE, \
+ .interrupt_priority = NRFX_WDT_CONFIG_IRQ_PRIORITY, \
+ }
+/**
+ * @brief This function initializes watchdog.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] wdt_event_handler Event handler provided by the user.
+ * Must not be NULL.
+ *
+ * @return NRFX_SUCCESS on success, otherwise an error code.
+ */
+nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
+ nrfx_wdt_event_handler_t wdt_event_handler);
+
+/**
+ * @brief This function allocate watchdog channel.
+ *
+ * @note This function can not be called after nrfx_wdt_start(void).
+ *
+ * @param[out] p_channel_id ID of granted channel.
+ *
+ * @return NRFX_SUCCESS on success, otherwise an error code.
+ */
+nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id);
+
+/**
+ * @brief This function starts watchdog.
+ *
+ * @note After calling this function the watchdog is started, so the user needs to feed all allocated
+ * watchdog channels to avoid reset. At least one watchdog channel has to be allocated.
+ */
+void nrfx_wdt_enable(void);
+
+/**
+ * @brief This function feeds the watchdog.
+ *
+ * @details Function feeds all allocated watchdog channels.
+ */
+void nrfx_wdt_feed(void);
+
+/**
+ * @brief This function feeds the invidual watchdog channel.
+ *
+ * @param[in] channel_id ID of watchdog channel.
+ */
+void nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id);
+
+/**@brief Function for returning a requested task address for the wdt driver module.
+ *
+ * @param[in] task One of the peripheral tasks.
+ *
+ * @retval Task address.
+ */
+__STATIC_INLINE uint32_t nrfx_wdt_ppi_task_addr(nrf_wdt_task_t task)
+{
+ return nrf_wdt_task_address_get(task);
+}
+
+/**@brief Function for returning a requested event address for the wdt driver module.
+ *
+ * @param[in] event One of the peripheral events.
+ *
+ * @retval Event address
+ */
+__STATIC_INLINE uint32_t nrfx_wdt_ppi_event_addr(nrf_wdt_event_t event)
+{
+ return nrf_wdt_event_address_get(event);
+}
+
+
+void nrfx_wdt_irq_handler(void);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_common.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_common.h
new file mode 100644
index 0000000..3b47ac2
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_common.h
@@ -0,0 +1,269 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_COMMON_H__
+#define NRFX_COMMON_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <nrf.h>
+#include <nrf_peripherals.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_common Common module
+ * @{
+ * @ingroup nrfx
+ * @brief Common module.
+ */
+
+/**
+ * @brief Macro for checking if the specified identifier is defined and it has
+ * a non-zero value.
+ *
+ * Normally, preprocessors treat all undefined identifiers as having the value
+ * zero. However, some tools, like static code analyzers, may issue a warning
+ * when such identifier is evaluated. This macro gives the possibility to suppress
+ * such warnings only in places where this macro is used for evaluation, not in
+ * the whole analyzed code.
+ */
+#define NRFX_CHECK(module_enabled) (module_enabled)
+
+/**
+ * @brief Macro for concatenating two tokens in macro expansion.
+ *
+ * @note This macro is expanded in two steps so that tokens given as macros
+ * themselves are fully expanded before they are merged.
+ *
+ * @param p1 First token.
+ * @param p2 Second token.
+ *
+ * @return The two tokens merged into one, unless they cannot together form
+ * a valid token (in such case, the preprocessor issues a warning and
+ * does not perform the concatenation).
+ *
+ * @sa NRFX_CONCAT_3
+ */
+#define NRFX_CONCAT_2(p1, p2) NRFX_CONCAT_2_(p1, p2)
+/**
+ * @brief Internal macro used by @ref NRFX_CONCAT_2 to perform the expansion
+ * in two steps.
+ */
+#define NRFX_CONCAT_2_(p1, p2) p1 ## p2
+
+/**
+ * @brief Macro for concatenating three tokens in macro expansion.
+ *
+ * @note This macro is expanded in two steps so that tokens given as macros
+ * themselves are fully expanded before they are merged.
+ *
+ * @param p1 First token.
+ * @param p2 Second token.
+ * @param p3 Third token.
+ *
+ * @return The three tokens merged into one, unless they cannot together form
+ * a valid token (in such case, the preprocessor issues a warning and
+ * does not perform the concatenation).
+ *
+ * @sa NRFX_CONCAT_2
+ */
+#define NRFX_CONCAT_3(p1, p2, p3) NRFX_CONCAT_3_(p1, p2, p3)
+/**
+ * @brief Internal macro used by @ref NRFX_CONCAT_3 to perform the expansion
+ * in two steps.
+ */
+#define NRFX_CONCAT_3_(p1, p2, p3) p1 ## p2 ## p3
+
+/**@brief Macro for performing rounded integer division (as opposed to
+ * truncating the result).
+ *
+ * @param a Numerator.
+ * @param b Denominator.
+ *
+ * @return Rounded (integer) result of dividing @c a by @c b.
+ */
+#define NRFX_ROUNDED_DIV(a, b) (((a) + ((b) / 2)) / (b))
+
+/**@brief Macro for checking if given lengths of EasyDMA transfers do not exceed
+ * the limit of the specified peripheral.
+ *
+ * @param peripheral Peripheral to check the lengths against.
+ * @param length1 First length to be checked.
+ * @param length2 Second length to be checked (pass 0 if not needed).
+ *
+ * @return
+ */
+#define NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, length1, length2) \
+ (((length1) < (1U << NRFX_CONCAT_2(peripheral, _EASYDMA_MAXCNT_SIZE))) && \
+ ((length2) < (1U << NRFX_CONCAT_2(peripheral, _EASYDMA_MAXCNT_SIZE))))
+
+/**@brief Macro for waiting until condition is met.
+ *
+ * @param[in] condition Condition to meet.
+ * @param[in] attempts Maximum number of condition checks. Must not be 0.
+ * @param[in] delay_us Delay between consecutive checks, in microseconds.
+ * @param[out] result Boolean variable to store the result of the wait process.
+ * Set to true if the condition is met or false otherwise.
+ */
+#define NRFX_WAIT_FOR(condition, attempts, delay_us, result) \
+do { \
+ result = false; \
+ uint32_t remaining_attempts = (attempts); \
+ do { \
+ if (condition) \
+ { \
+ result = true; \
+ break; \
+ } \
+ NRFX_DELAY_US(delay_us); \
+ } while (--remaining_attempts); \
+} while(0)
+
+/**
+ * @brief IRQ handler type.
+ */
+typedef void (* nrfx_irq_handler_t)(void);
+
+/**
+ * @brief Driver state.
+ */
+typedef enum
+{
+ NRFX_DRV_STATE_UNINITIALIZED, ///< Uninitialized.
+ NRFX_DRV_STATE_INITIALIZED, ///< Initialized but powered off.
+ NRFX_DRV_STATE_POWERED_ON, ///< Initialized and powered on.
+} nrfx_drv_state_t;
+
+
+/**
+ * @brief Function for checking if an object is placed in the Data RAM region.
+ *
+ * Several peripherals (the ones using EasyDMA) require the transfer buffers
+ * to be placed in the Data RAM region. This function can be used to check if
+ * this condition is met.
+ *
+ * @param[in] p_object Pointer to an object whose location is to be checked.
+ *
+ * @retval true If the pointed object is located in the Data RAM region.
+ * @retval false Otherwise.
+ */
+__STATIC_INLINE bool nrfx_is_in_ram(void const * p_object);
+
+/**
+ * @brief Function for getting the interrupt number for a specific peripheral.
+ *
+ * @param[in] p_reg Peripheral base pointer.
+ *
+ * @return Interrupt number associated with the pointed peripheral.
+ */
+__STATIC_INLINE IRQn_Type nrfx_get_irq_number(void const * p_reg);
+
+/**
+ * @brief Function for converting an INTEN register bit position to the
+ * corresponding event identifier.
+ *
+ * The event identifier is the offset between the event register address and
+ * the peripheral base address, and is equal (thus, can be directly cast) to
+ * the corresponding value of the enumerated type from HAL (nrf_*_event_t).
+
+ * @param bit INTEN register bit position.
+ *
+ * @return Event identifier.
+ *
+ * @sa nrfx_event_to_bitpos
+ */
+__STATIC_INLINE uint32_t nrfx_bitpos_to_event(uint32_t bit);
+
+/**
+ * @brief Function for converting an event identifier to the corresponding
+ * INTEN register bit position.
+ *
+ * The event identifier is the offset between the event register address and
+ * the peripheral base address, and is equal (thus, can be directly cast) to
+ * the corresponding value of the enumerated type from HAL (nrf_*_event_t).
+ *
+ * @param event Event identifier.
+ *
+ * @return INTEN register bit position.
+ *
+ * @sa nrfx_bitpos_to_event
+ */
+__STATIC_INLINE uint32_t nrfx_event_to_bitpos(uint32_t event);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE bool nrfx_is_in_ram(void const * p_object)
+{
+ return ((((uint32_t)p_object) & 0xE0000000u) == 0x20000000u);
+}
+
+__STATIC_INLINE IRQn_Type nrfx_get_irq_number(void const * p_reg)
+{
+ uint8_t irq_number = (uint8_t)(((uint32_t)p_reg) >> 12u);
+ return (IRQn_Type)irq_number;
+}
+
+__STATIC_INLINE uint32_t nrfx_bitpos_to_event(uint32_t bit)
+{
+ static const uint32_t event_reg_offset = 0x100u;
+ return event_reg_offset + (bit * sizeof(uint32_t));
+}
+
+__STATIC_INLINE uint32_t nrfx_event_to_bitpos(uint32_t event)
+{
+ static const uint32_t event_reg_offset = 0x100u;
+ return (event - event_reg_offset) / sizeof(uint32_t);
+}
+
+#endif
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_COMMON_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_errors.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_errors.h
new file mode 100644
index 0000000..f900be8
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/nrfx_errors.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_ERRORS_H__
+#define NRFX_ERRORS_H__
+
+#if !NRFX_CHECK(NRFX_CUSTOM_ERROR_CODES)
+
+/**
+ * @defgroup nrfx_error_codes Global Error Codes
+ * @{
+ * @ingroup nrfx
+ *
+ * @brief Global error codes definitions.
+ */
+
+#define NRFX_ERROR_BASE_NUM 0x0BAD0000
+#define NRFX_ERROR_DRIVERS_BASE_NUM (NRFX_ERROR_BASE_NUM + 0x10000)
+
+/** @brief Enumerated type for error codes. */
+typedef enum {
+ NRFX_SUCCESS = (NRFX_ERROR_BASE_NUM + 0), ///< Operation performed successfully.
+ NRFX_ERROR_INTERNAL = (NRFX_ERROR_BASE_NUM + 1), ///< Internal error.
+ NRFX_ERROR_NO_MEM = (NRFX_ERROR_BASE_NUM + 2), ///< No memory for operation.
+ NRFX_ERROR_NOT_SUPPORTED = (NRFX_ERROR_BASE_NUM + 3), ///< Not supported.
+ NRFX_ERROR_INVALID_PARAM = (NRFX_ERROR_BASE_NUM + 4), ///< Invalid parameter.
+ NRFX_ERROR_INVALID_STATE = (NRFX_ERROR_BASE_NUM + 5), ///< Invalid state, operation disallowed in this state.
+ NRFX_ERROR_INVALID_LENGTH = (NRFX_ERROR_BASE_NUM + 6), ///< Invalid length.
+ NRFX_ERROR_TIMEOUT = (NRFX_ERROR_BASE_NUM + 7), ///< Operation timed out.
+ NRFX_ERROR_FORBIDDEN = (NRFX_ERROR_BASE_NUM + 8), ///< Operation is forbidden.
+ NRFX_ERROR_NULL = (NRFX_ERROR_BASE_NUM + 9), ///< Null pointer.
+ NRFX_ERROR_INVALID_ADDR = (NRFX_ERROR_BASE_NUM + 10), ///< Bad memory address.
+ NRFX_ERROR_BUSY = (NRFX_ERROR_BASE_NUM + 11), ///< Busy.
+ NRFX_ERROR_ALREADY_INITIALIZED = (NRFX_ERROR_BASE_NUM + 12), ///< Module already initialized.
+
+ NRFX_ERROR_DRV_TWI_ERR_OVERRUN = (NRFX_ERROR_DRIVERS_BASE_NUM + 0), ///< TWI error: Overrun.
+ NRFX_ERROR_DRV_TWI_ERR_ANACK = (NRFX_ERROR_DRIVERS_BASE_NUM + 1), ///< TWI error: Address not acknowledged.
+ NRFX_ERROR_DRV_TWI_ERR_DNACK = (NRFX_ERROR_DRIVERS_BASE_NUM + 2) ///< TWI error: Data not acknowledged.
+} nrfx_err_t;
+
+/** @} */
+
+#endif // !NRFX_CHECK(NRFX_CUSTOM_ERROR_CODES)
+
+#endif // NRFX_ERRORS_H__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_adc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_adc.c
new file mode 100644
index 0000000..cbe51fa
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_adc.c
@@ -0,0 +1,324 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_ADC_ENABLED)
+
+#include <nrfx_adc.h>
+
+#define NRFX_LOG_MODULE ADC
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) (event == NRF_ADC_EVENT_END ? "NRF_ADC_EVENT_END" : "UNKNOWN EVENT")
+
+typedef struct
+{
+ nrfx_adc_event_handler_t event_handler;
+ nrfx_adc_channel_t * p_head;
+ nrfx_adc_channel_t * p_current_conv;
+ nrf_adc_value_t * p_buffer;
+ uint16_t size;
+ uint16_t idx;
+ nrfx_drv_state_t state;
+} adc_cb_t;
+
+static adc_cb_t m_cb;
+
+nrfx_err_t nrfx_adc_init(nrfx_adc_config_t const * p_config,
+ nrfx_adc_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ nrfx_err_t err_code;
+
+ if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ nrf_adc_event_clear(NRF_ADC_EVENT_END);
+ if (event_handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(ADC_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(ADC_IRQn);
+ }
+ m_cb.event_handler = event_handler;
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_adc_uninit(void)
+{
+ m_cb.p_head = NULL;
+ NRFX_IRQ_DISABLE(ADC_IRQn);
+ nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
+ nrf_adc_task_trigger(NRF_ADC_TASK_STOP);
+
+ m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+void nrfx_adc_channel_enable(nrfx_adc_channel_t * const p_channel)
+{
+ NRFX_ASSERT(!nrfx_adc_is_busy());
+
+ p_channel->p_next = NULL;
+ if (m_cb.p_head == NULL)
+ {
+ m_cb.p_head = p_channel;
+ }
+ else
+ {
+ nrfx_adc_channel_t * p_curr_channel = m_cb.p_head;
+ while (p_curr_channel->p_next != NULL)
+ {
+ NRFX_ASSERT(p_channel != p_curr_channel);
+ p_curr_channel = p_curr_channel->p_next;
+ }
+ p_curr_channel->p_next = p_channel;
+ }
+
+ NRFX_LOG_INFO("Enabled.");
+}
+
+void nrfx_adc_channel_disable(nrfx_adc_channel_t * const p_channel)
+{
+ NRFX_ASSERT(m_cb.p_head);
+ NRFX_ASSERT(!nrfx_adc_is_busy());
+
+ nrfx_adc_channel_t * p_curr_channel = m_cb.p_head;
+ nrfx_adc_channel_t * p_prev_channel = NULL;
+ while (p_curr_channel != p_channel)
+ {
+ p_prev_channel = p_curr_channel;
+ p_curr_channel = p_curr_channel->p_next;
+ NRFX_ASSERT(p_curr_channel != NULL);
+ }
+ if (p_prev_channel)
+ {
+ p_prev_channel->p_next = p_curr_channel->p_next;
+ }
+ else
+ {
+ m_cb.p_head = p_curr_channel->p_next;
+ }
+
+ NRFX_LOG_INFO("Disabled.");
+}
+
+void nrfx_adc_sample(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(!nrf_adc_busy_check());
+ nrf_adc_task_trigger(NRF_ADC_TASK_START);
+}
+
+nrfx_err_t nrfx_adc_sample_convert(nrfx_adc_channel_t const * const p_channel,
+ nrf_adc_value_t * p_value)
+{
+ nrfx_err_t err_code;
+
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ if (m_cb.state == NRFX_DRV_STATE_POWERED_ON)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ m_cb.state = NRFX_DRV_STATE_POWERED_ON;
+
+ nrf_adc_init(&p_channel->config);
+ nrf_adc_enable();
+ nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
+ nrf_adc_task_trigger(NRF_ADC_TASK_START);
+ if (p_value)
+ {
+ while (!nrf_adc_event_check(NRF_ADC_EVENT_END)) {}
+ nrf_adc_event_clear(NRF_ADC_EVENT_END);
+ *p_value = (nrf_adc_value_t)nrf_adc_result_get();
+ nrf_adc_disable();
+
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ }
+ else
+ {
+ NRFX_ASSERT(m_cb.event_handler);
+ m_cb.p_buffer = NULL;
+ nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
+ }
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+}
+
+static bool adc_sample_process()
+{
+ nrf_adc_event_clear(NRF_ADC_EVENT_END);
+ nrf_adc_disable();
+ m_cb.p_buffer[m_cb.idx] = (nrf_adc_value_t)nrf_adc_result_get();
+ m_cb.idx++;
+ if (m_cb.idx < m_cb.size)
+ {
+ bool task_trigger = false;
+ if (m_cb.p_current_conv->p_next == NULL)
+ {
+ m_cb.p_current_conv = m_cb.p_head;
+ }
+ else
+ {
+ m_cb.p_current_conv = m_cb.p_current_conv->p_next;
+ task_trigger = true;
+ }
+ nrf_adc_init(&m_cb.p_current_conv->config);
+ nrf_adc_enable();
+ if (task_trigger)
+ {
+ nrf_adc_task_trigger(NRF_ADC_TASK_START);
+ }
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+nrfx_err_t nrfx_adc_buffer_convert(nrf_adc_value_t * buffer, uint16_t size)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrfx_err_t err_code;
+
+ NRFX_LOG_INFO("Number of samples requested to convert: %d.", size);
+
+ if (m_cb.state == NRFX_DRV_STATE_POWERED_ON)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ m_cb.state = NRFX_DRV_STATE_POWERED_ON;
+ m_cb.p_current_conv = m_cb.p_head;
+ m_cb.size = size;
+ m_cb.idx = 0;
+ m_cb.p_buffer = buffer;
+ nrf_adc_init(&m_cb.p_current_conv->config);
+ nrf_adc_event_clear(NRF_ADC_EVENT_END);
+ nrf_adc_enable();
+ if (m_cb.event_handler)
+ {
+ nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
+ }
+ else
+ {
+ while (1)
+ {
+ while (!nrf_adc_event_check(NRF_ADC_EVENT_END)){}
+
+ if (adc_sample_process())
+ {
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ break;
+ }
+ }
+ }
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+}
+
+bool nrfx_adc_is_busy(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ return (m_cb.state == NRFX_DRV_STATE_POWERED_ON) ? true : false;
+}
+
+void nrfx_adc_irq_handler(void)
+{
+ if (m_cb.p_buffer == NULL)
+ {
+ nrf_adc_event_clear(NRF_ADC_EVENT_END);
+ NRFX_LOG_DEBUG("Event: %s.",NRFX_LOG_ERROR_STRING_GET(NRF_ADC_EVENT_END));
+ nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
+ nrf_adc_disable();
+ nrfx_adc_evt_t evt;
+ evt.type = NRFX_ADC_EVT_SAMPLE;
+ evt.data.sample.sample = (nrf_adc_value_t)nrf_adc_result_get();
+ NRFX_LOG_DEBUG("ADC data:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)(&evt.data.sample.sample), sizeof(nrf_adc_value_t));
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ m_cb.event_handler(&evt);
+ }
+ else if (adc_sample_process())
+ {
+ NRFX_LOG_DEBUG("Event: %s.", NRFX_LOG_ERROR_STRING_GET(NRF_ADC_EVENT_END));
+ nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
+ nrfx_adc_evt_t evt;
+ evt.type = NRFX_ADC_EVT_DONE;
+ evt.data.done.p_buffer = m_cb.p_buffer;
+ evt.data.done.size = m_cb.size;
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_DEBUG("ADC data:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)m_cb.p_buffer, m_cb.size * sizeof(nrf_adc_value_t));
+ m_cb.event_handler(&evt);
+ }
+}
+
+#endif // NRFX_CHECK(NRFX_ADC_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_clock.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_clock.c
new file mode 100644
index 0000000..8e1d14e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_clock.c
@@ -0,0 +1,381 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
+
+#include <nrfx_clock.h>
+
+#define NRFX_LOG_MODULE CLOCK
+#include <nrfx_log.h>
+
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+extern bool nrfx_power_irq_enabled;
+#endif
+
+#define EVT_TO_STR(event) \
+ (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \
+ (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \
+ (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \
+ (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \
+ "UNKNOWN EVENT"))))
+
+
+/*lint -save -e652 */
+#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC
+#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal
+#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth
+/*lint -restore */
+
+#if (NRFX_CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC)
+#define CALIBRATION_SUPPORT 1
+#else
+#define CALIBRATION_SUPPORT 0
+#endif
+
+#if defined(NRF52810_XXAA) || \
+ defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
+ defined(NRF52840_XXAA)
+// Enable workaround for nRF52 anomaly 192 (LFRC oscillator frequency is wrong
+// after calibration, exceeding 500 ppm).
+#define USE_WORKAROUND_FOR_ANOMALY_192
+
+// Enable workaround for nRF52 anomaly 201 (EVENTS_HFCLKSTARTED might be generated twice).
+#define USE_WORKAROUND_FOR_ANOMALY_201
+#endif
+
+typedef enum
+{
+ CAL_STATE_IDLE,
+ CAL_STATE_CAL
+} nrfx_clock_cal_state_t;
+
+/**@brief CLOCK control block. */
+typedef struct
+{
+ nrfx_clock_event_handler_t event_handler;
+ bool module_initialized; /*< Indicate the state of module */
+#if defined(USE_WORKAROUND_FOR_ANOMALY_201)
+ bool hfclk_started; /*< Anomaly 201 workaround. */
+#endif
+
+#if CALIBRATION_SUPPORT
+ volatile nrfx_clock_cal_state_t cal_state;
+#endif // CALIBRATION_SUPPORT
+} nrfx_clock_cb_t;
+
+static nrfx_clock_cb_t m_clock_cb;
+
+/**
+ * This variable is used to check whether common POWER_CLOCK common interrupt
+ * should be disabled or not if @ref nrfx_power tries to disable the interrupt.
+ */
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+bool nrfx_clock_irq_enabled;
+#endif
+
+#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
+
+// ANOMALY 132 - LFCLK needs to avoid frame from 66us to 138us after LFCLK stop. This solution
+// applies delay of 138us before starting LFCLK.
+#define ANOMALY_132_REQ_DELAY_US 138UL
+
+// nRF52832 is clocked with 64MHz.
+#define ANOMALY_132_NRF52832_FREQ_MHZ 64UL
+
+// Convert time to cycles.
+#define ANOMALY_132_DELAY_CYCLES (ANOMALY_132_REQ_DELAY_US * ANOMALY_132_NRF52832_FREQ_MHZ)
+
+/**
+ * @brief Function for applying delay of 138us before starting LFCLK.
+ */
+static void nrfx_clock_anomaly_132(void)
+{
+ uint32_t cyccnt_inital;
+ uint32_t core_debug;
+ uint32_t dwt_ctrl;
+
+ // Preserve DEMCR register to do not influence into its configuration. Enable the trace and
+ // debug blocks. It is required to read and write data to DWT block.
+ core_debug = CoreDebug->DEMCR;
+ CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk;
+
+ // Preserve CTRL register in DWT block to do not influence into its configuration. Make sure
+ // that cycle counter is enabled.
+ dwt_ctrl = DWT->CTRL;
+ DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk;
+
+ // Store start value of cycle counter.
+ cyccnt_inital = DWT->CYCCNT;
+
+ // Delay required time.
+ while ((DWT->CYCCNT - cyccnt_inital) < ANOMALY_132_DELAY_CYCLES)
+ {}
+
+ // Restore preserved registers.
+ DWT->CTRL = dwt_ctrl;
+ CoreDebug->DEMCR = core_debug;
+}
+
+#endif // defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
+
+nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler)
+{
+ NRFX_ASSERT(event_handler);
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ if (m_clock_cb.module_initialized)
+ {
+ err_code = NRFX_ERROR_ALREADY_INITIALIZED;
+ }
+ else
+ {
+#if CALIBRATION_SUPPORT
+ m_clock_cb.cal_state = CAL_STATE_IDLE;
+#endif
+ m_clock_cb.event_handler = event_handler;
+ m_clock_cb.module_initialized = true;
+#if defined(USE_WORKAROUND_FOR_ANOMALY_201)
+ m_clock_cb.hfclk_started = false;
+#endif
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_clock_enable(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrfx_power_clock_irq_init();
+ nrf_clock_lf_src_set((nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
+
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+ nrfx_clock_irq_enabled = true;
+#endif
+
+ NRFX_LOG_INFO("Module enabled.");
+}
+
+void nrfx_clock_disable(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+ NRFX_ASSERT(nrfx_clock_irq_enabled);
+ if (!nrfx_power_irq_enabled)
+#endif
+ {
+ NRFX_IRQ_DISABLE(POWER_CLOCK_IRQn);
+ }
+ nrf_clock_int_disable(CLOCK_INTENSET_HFCLKSTARTED_Msk |
+ CLOCK_INTENSET_LFCLKSTARTED_Msk |
+ CLOCK_INTENSET_DONE_Msk |
+ CLOCK_INTENSET_CTTO_Msk);
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+ nrfx_clock_irq_enabled = false;
+#endif
+ NRFX_LOG_INFO("Module disabled.");
+}
+
+void nrfx_clock_uninit(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrfx_clock_lfclk_stop();
+ nrfx_clock_hfclk_stop();
+ m_clock_cb.module_initialized = false;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_clock_lfclk_start(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
+ nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
+
+#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
+ nrfx_clock_anomaly_132();
+#endif
+
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
+}
+
+void nrfx_clock_lfclk_stop(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP);
+ while (nrf_clock_lf_is_running())
+ {}
+}
+
+void nrfx_clock_hfclk_start(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
+ nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK);
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
+}
+
+void nrfx_clock_hfclk_stop(void)
+{
+ NRFX_ASSERT(m_clock_cb.module_initialized);
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP);
+ while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY))
+ {}
+#if defined(USE_WORKAROUND_FOR_ANOMALY_201)
+ m_clock_cb.hfclk_started = false;
+#endif
+}
+
+nrfx_err_t nrfx_clock_calibration_start(void)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+#if CALIBRATION_SUPPORT
+ if (nrfx_clock_hfclk_is_running() == false)
+ {
+ return NRFX_ERROR_INVALID_STATE;
+ }
+
+ if (nrfx_clock_lfclk_is_running() == false)
+ {
+ return NRFX_ERROR_INVALID_STATE;
+ }
+
+ if (m_clock_cb.cal_state == CAL_STATE_IDLE)
+ {
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
+ nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK);
+ m_clock_cb.cal_state = CAL_STATE_CAL;
+#if defined(USE_WORKAROUND_FOR_ANOMALY_192)
+ *(volatile uint32_t *)0x40000C34 = 0x00000002;
+#endif
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL);
+ }
+ else
+ {
+ err_code = NRFX_ERROR_BUSY;
+ }
+#endif // CALIBRATION_SUPPORT
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_clock_is_calibrating(void)
+{
+#if CALIBRATION_SUPPORT
+ if (m_clock_cb.cal_state == CAL_STATE_CAL)
+ {
+ return NRFX_ERROR_BUSY;
+ }
+#endif
+ return NRFX_SUCCESS;
+}
+
+void nrfx_clock_calibration_timer_start(uint8_t interval)
+{
+ nrf_clock_cal_timer_timeout_set(interval);
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
+ nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK);
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART);
+}
+
+void nrfx_clock_calibration_timer_stop(void)
+{
+ nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
+ nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP);
+}
+
+void nrfx_clock_irq_handler(void)
+{
+ if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
+ {
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED));
+ nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
+
+#if defined(USE_WORKAROUND_FOR_ANOMALY_201)
+ if (!m_clock_cb.hfclk_started)
+ {
+ m_clock_cb.hfclk_started = true;
+ m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
+ }
+#else
+ m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
+#endif
+ }
+ if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
+ {
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED));
+ nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
+
+ m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED);
+ }
+#if CALIBRATION_SUPPORT
+ if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
+ {
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_CTTO));
+ nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
+
+ m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO);
+ }
+
+ if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
+ {
+#if defined(USE_WORKAROUND_FOR_ANOMALY_192)
+ *(volatile uint32_t *)0x40000C34 = 0x00000000;
+#endif
+ nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_DONE));
+ nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
+ m_clock_cb.cal_state = CAL_STATE_IDLE;
+ m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE);
+ }
+#endif // CALIBRATION_SUPPORT
+}
+
+#undef NRF_CLOCK_LFCLK_RC
+#undef NRF_CLOCK_LFCLK_Xtal
+#undef NRF_CLOCK_LFCLK_Synth
+
+#endif // NRFX_CHECK(NRFX_CLOCK_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_comp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_comp.c
new file mode 100644
index 0000000..63572d5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_comp.c
@@ -0,0 +1,211 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_COMP_ENABLED)
+
+#include <nrfx_comp.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE COMP
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_COMP_EVENT_READY ? "NRF_COMP_EVENT_READY" : \
+ (event == NRF_COMP_EVENT_DOWN ? "NRF_COMP_EVENT_DOWN" : \
+ (event == NRF_COMP_EVENT_UP ? "NRF_COMP_EVENT_UP" : \
+ (event == NRF_COMP_EVENT_CROSS ? "NRF_COMP_EVENT_CROSS" : \
+ "UNKNOWN ERROR"))))
+
+
+static nrfx_comp_event_handler_t m_comp_event_handler = NULL;
+static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
+
+static void comp_execute_handler(nrf_comp_event_t event, uint32_t event_mask)
+{
+ if (nrf_comp_event_check(event) && nrf_comp_int_enable_check(event_mask))
+ {
+ nrf_comp_event_clear(event);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
+
+ m_comp_event_handler(event);
+ }
+}
+
+void nrfx_comp_irq_handler(void)
+{
+ comp_execute_handler(NRF_COMP_EVENT_READY, COMP_INTENSET_READY_Msk);
+ comp_execute_handler(NRF_COMP_EVENT_DOWN, COMP_INTENSET_DOWN_Msk);
+ comp_execute_handler(NRF_COMP_EVENT_UP, COMP_INTENSET_UP_Msk);
+ comp_execute_handler(NRF_COMP_EVENT_CROSS, COMP_INTENSET_CROSS_Msk);
+}
+
+
+nrfx_err_t nrfx_comp_init(nrfx_comp_config_t const * p_config,
+ nrfx_comp_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ nrfx_err_t err_code;
+
+ if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
+ { // COMP driver is already initialized
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_comp_event_handler = event_handler;
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ if (nrfx_prs_acquire(NRF_COMP, nrfx_comp_irq_handler) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif
+
+ nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
+ nrf_comp_enable();
+
+ // Clear events to be sure there are no leftovers.
+ nrf_comp_event_clear(NRF_COMP_EVENT_READY);
+ nrf_comp_event_clear(NRF_COMP_EVENT_DOWN);
+ nrf_comp_event_clear(NRF_COMP_EVENT_UP);
+ nrf_comp_event_clear(NRF_COMP_EVENT_CROSS);
+
+ nrf_comp_ref_set(p_config->reference);
+
+ //If external source is chosen, write to appropriate register.
+ if (p_config->reference == COMP_REFSEL_REFSEL_ARef)
+ {
+ nrf_comp_ext_ref_set(p_config->ext_ref);
+ }
+
+ nrf_comp_th_set(p_config->threshold);
+ nrf_comp_main_mode_set(p_config->main_mode);
+ nrf_comp_speed_mode_set(p_config->speed_mode);
+ nrf_comp_hysteresis_set(p_config->hyst);
+#if defined (COMP_ISOURCE_ISOURCE_Msk)
+ nrf_comp_isource_set(p_config->isource);
+#endif
+ nrf_comp_shorts_disable(NRFX_COMP_SHORT_STOP_AFTER_CROSS_EVT |
+ NRFX_COMP_SHORT_STOP_AFTER_UP_EVT |
+ NRFX_COMP_SHORT_STOP_AFTER_DOWN_EVT);
+ nrf_comp_int_disable(COMP_INTENCLR_CROSS_Msk |
+ COMP_INTENCLR_UP_Msk |
+ COMP_INTENCLR_DOWN_Msk |
+ COMP_INTENCLR_READY_Msk);
+
+ nrf_comp_input_select(p_config->input);
+
+ NRFX_IRQ_PRIORITY_SET(COMP_LPCOMP_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(COMP_LPCOMP_IRQn);
+
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_comp_uninit(void)
+{
+ NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_IRQ_DISABLE(COMP_LPCOMP_IRQn);
+ nrf_comp_disable();
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(NRF_COMP);
+#endif
+ m_state = NRFX_DRV_STATE_UNINITIALIZED;
+ m_comp_event_handler = NULL;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_comp_pin_select(nrf_comp_input_t psel)
+{
+ bool comp_enable_state = nrf_comp_enable_check();
+ nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
+ if (m_state == NRFX_DRV_STATE_POWERED_ON)
+ {
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+ }
+ nrf_comp_disable();
+ nrf_comp_input_select(psel);
+ if (comp_enable_state == true)
+ {
+ nrf_comp_enable();
+ }
+}
+
+void nrfx_comp_start(uint32_t comp_int_mask, uint32_t comp_shorts_mask)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_comp_int_enable(comp_int_mask);
+ nrf_comp_shorts_enable(comp_shorts_mask);
+ nrf_comp_task_trigger(NRF_COMP_TASK_START);
+ m_state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled.");
+}
+
+void nrfx_comp_stop(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_comp_shorts_disable(UINT32_MAX);
+ nrf_comp_int_disable(UINT32_MAX);
+ nrf_comp_task_trigger(NRF_COMP_TASK_STOP);
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled.");
+}
+
+uint32_t nrfx_comp_sample()
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_comp_task_trigger(NRF_COMP_TASK_SAMPLE);
+ return nrf_comp_result_get();
+}
+
+#endif // NRFX_CHECK(NRFX_COMP_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_gpiote.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_gpiote.c
new file mode 100644
index 0000000..8412b60
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_gpiote.c
@@ -0,0 +1,826 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_GPIOTE_ENABLED)
+
+#include <nrfx_gpiote.h>
+#include "nrf_bitmask.h"
+#include <string.h>
+
+#define NRFX_LOG_MODULE GPIOTE
+#include <nrfx_log.h>
+
+
+#define FORBIDDEN_HANDLER_ADDRESS ((nrfx_gpiote_evt_handler_t)UINT32_MAX)
+#define PIN_NOT_USED (-1)
+#define PIN_USED (-2)
+#define NO_CHANNELS (-1)
+#define SENSE_FIELD_POS (6)
+#define SENSE_FIELD_MASK (0xC0)
+
+/**
+ * @brief Macro for converting task-event index to an address of an event register.
+ *
+ * Macro utilizes the fact that registers are grouped together in ascending order.
+ */
+#define TE_IDX_TO_EVENT_ADDR(idx) (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0 + \
+ (sizeof(uint32_t) * (idx)))
+
+/**
+ * @brief Macro for converting task-event index of OUT task to an address of a task register.
+ *
+ * Macro utilizes the fact that registers are grouped together in ascending order.
+ */
+#define TE_OUT_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0 + \
+ (sizeof(uint32_t) * (idx)))
+
+#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Macro for converting task-event index of SET task to an address of a task register.
+ *
+ * Macro utilizes the fact that registers are grouped together in ascending order.
+ */
+#define TE_SET_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_SET_0 + \
+ (sizeof(uint32_t) * (idx)))
+
+#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Macro for converting task-event index of CLR task to an address of a task register.
+ *
+ * Macro utilizes the fact that registers are grouped together in ascending order.
+ */
+#define TE_CLR_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_CLR_0 + \
+ (sizeof(uint32_t) * (idx)))
+
+#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
+
+/*lint -save -e571*/ /* Suppress "Warning 571: Suspicious cast" */
+typedef struct
+{
+ nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
+ int8_t pin_assignments[NUMBER_OF_PINS];
+ int8_t port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
+ uint8_t configured_pins[((NUMBER_OF_PINS)+7) / 8];
+ nrfx_drv_state_t state;
+} gpiote_control_block_t;
+
+static gpiote_control_block_t m_cb;
+
+__STATIC_INLINE bool pin_in_use(uint32_t pin)
+{
+ return (m_cb.pin_assignments[pin] != PIN_NOT_USED);
+}
+
+
+__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
+{
+ return (m_cb.pin_assignments[pin] == PIN_USED);
+}
+
+
+__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
+{
+ return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < GPIOTE_CH_NUM) ?
+ true : false;
+}
+
+
+__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
+{
+ return (m_cb.pin_assignments[pin] >= GPIOTE_CH_NUM);
+}
+
+
+__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
+{
+ return (m_cb.pin_assignments[pin] >= 0);
+}
+
+
+__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
+ uint32_t channel_id,
+ nrfx_gpiote_evt_handler_t handler,
+ bool is_channel)
+{
+ m_cb.pin_assignments[pin] = channel_id;
+ m_cb.handlers[channel_id] = handler;
+ if (!is_channel)
+ {
+ m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)pin;
+ }
+}
+
+
+__STATIC_INLINE void pin_in_use_set(uint32_t pin)
+{
+ m_cb.pin_assignments[pin] = PIN_USED;
+}
+
+
+__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
+{
+ m_cb.pin_assignments[pin] = PIN_NOT_USED;
+}
+
+
+__STATIC_INLINE void pin_configured_set(uint32_t pin)
+{
+ nrf_bitmask_bit_set(pin, m_cb.configured_pins);
+}
+
+__STATIC_INLINE void pin_configured_clear(uint32_t pin)
+{
+ nrf_bitmask_bit_clear(pin, m_cb.configured_pins);
+}
+
+__STATIC_INLINE bool pin_configured_check(uint32_t pin)
+{
+ return 0 != nrf_bitmask_bit_is_set(pin, m_cb.configured_pins);
+}
+
+__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
+{
+ return m_cb.pin_assignments[pin];
+}
+
+
+__STATIC_INLINE nrfx_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
+{
+ return m_cb.handlers[channel];
+}
+
+
+static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
+{
+ int8_t channel_id = NO_CHANNELS;
+ uint32_t i;
+
+ uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM;
+ uint32_t end_idx =
+ channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
+
+ // critical section
+
+ for (i = start_idx; i < end_idx; i++)
+ {
+ if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
+ {
+ pin_in_use_by_te_set(pin, i, handler, channel);
+ channel_id = i;
+ break;
+ }
+ }
+ // critical section
+ return channel_id;
+}
+
+
+static void channel_free(uint8_t channel_id)
+{
+ m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
+ if (channel_id >= GPIOTE_CH_NUM)
+ {
+ m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)PIN_NOT_USED;
+ }
+}
+
+
+nrfx_err_t nrfx_gpiote_init(void)
+{
+ nrfx_err_t err_code;
+
+ if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ uint8_t i;
+
+ for (i = 0; i < NUMBER_OF_PINS; i++)
+ {
+ pin_in_use_clear(i);
+ }
+
+ for (i = 0; i < (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
+ {
+ channel_free(i);
+ }
+
+ memset(m_cb.configured_pins, 0, sizeof(m_cb.configured_pins));
+
+ NRFX_IRQ_PRIORITY_SET(GPIOTE_IRQn, NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
+ NRFX_IRQ_ENABLE(GPIOTE_IRQn);
+ nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
+ nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+bool nrfx_gpiote_is_init(void)
+{
+ return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false;
+}
+
+
+void nrfx_gpiote_uninit(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ uint32_t i;
+
+ for (i = 0; i < NUMBER_OF_PINS; i++)
+ {
+ if (pin_in_use_as_non_task_out(i))
+ {
+ nrfx_gpiote_out_uninit(i);
+ }
+ else if ( pin_in_use_by_gpiote(i))
+ {
+ /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
+ * so it can be called on all pins used by GPIOTE.
+ */
+ nrfx_gpiote_in_uninit(i);
+ }
+ }
+ m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+
+nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,
+ nrfx_gpiote_out_config_t const * p_config)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
+ NRFX_ASSERT(p_config);
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (pin_in_use(pin))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ if (p_config->task_pin)
+ {
+ int8_t channel = channel_port_alloc(pin, NULL, true);
+
+ if (channel != NO_CHANNELS)
+ {
+ nrf_gpiote_task_configure((uint32_t)channel,
+ pin,
+ p_config->action,
+ p_config->init_state);
+ }
+ else
+ {
+ err_code = NRFX_ERROR_NO_MEM;
+ }
+ }
+ else
+ {
+ pin_in_use_set(pin);
+ }
+
+ if (err_code == NRFX_SUCCESS)
+ {
+ if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
+ {
+ nrf_gpio_pin_set(pin);
+ }
+ else
+ {
+ nrf_gpio_pin_clear(pin);
+ }
+
+ nrf_gpio_cfg_output(pin);
+ pin_configured_set(pin);
+ }
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+
+ if (pin_in_use_by_te(pin))
+ {
+ channel_free((uint8_t)channel_port_get(pin));
+ nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
+ }
+ pin_in_use_clear(pin);
+
+ if (pin_configured_check(pin))
+ {
+ nrf_gpio_cfg_default(pin);
+ pin_configured_clear(pin);
+ }
+}
+
+
+void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(!pin_in_use_by_te(pin));
+
+ nrf_gpio_pin_set(pin);
+}
+
+
+void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(!pin_in_use_by_te(pin));
+
+ nrf_gpio_pin_clear(pin);
+}
+
+
+void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(!pin_in_use_by_te(pin));
+
+ nrf_gpio_pin_toggle(pin);
+}
+
+
+void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_task_enable((uint32_t)m_cb.pin_assignments[pin]);
+}
+
+
+void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_task_disable((uint32_t)m_cb.pin_assignments[pin]);
+}
+
+
+uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ return nrf_gpiote_task_addr_get(task);
+}
+
+
+#if defined(GPIOTE_FEATURE_SET_PRESENT)
+uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ return nrf_gpiote_task_addr_get(task);
+}
+
+
+#endif // defined(GPIOTE_FEATURE_SET_PRESENT)
+
+#if defined(GPIOTE_FEATURE_CLR_PRESENT)
+uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ return nrf_gpiote_task_addr_get(task);
+}
+
+
+#endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
+
+void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_outinit_t init_val =
+ state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
+ nrf_gpiote_task_force((uint32_t)m_cb.pin_assignments[pin], init_val);
+}
+
+
+void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ nrf_gpiote_task_set(task);
+}
+
+
+#if defined(GPIOTE_FEATURE_SET_PRESENT)
+void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ nrf_gpiote_task_set(task);
+}
+
+
+#endif // defined(GPIOTE_FEATURE_SET_PRESENT)
+
+#if defined(GPIOTE_FEATURE_CLR_PRESENT)
+void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use(pin));
+ NRFX_ASSERT(pin_in_use_by_te(pin));
+
+ nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
+ nrf_gpiote_task_set(task);
+}
+
+
+#endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
+
+nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
+ nrfx_gpiote_in_config_t const * p_config,
+ nrfx_gpiote_evt_handler_t evt_handler)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ /* Only one GPIOTE channel can be assigned to one physical pin. */
+ if (pin_in_use_by_gpiote(pin))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
+ if (channel != NO_CHANNELS)
+ {
+ if (!p_config->skip_gpio_setup)
+ {
+ if (p_config->is_watcher)
+ {
+ nrf_gpio_cfg_watcher(pin);
+ }
+ else
+ {
+ nrf_gpio_cfg_input(pin, p_config->pull);
+ }
+ pin_configured_set(pin);
+ }
+
+ if (p_config->hi_accuracy)
+ {
+ nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
+ }
+ else
+ {
+ m_cb.port_handlers_pins[channel -
+ GPIOTE_CH_NUM] |= (p_config->sense) << SENSE_FIELD_POS;
+ }
+ }
+ else
+ {
+ err_code = NRFX_ERROR_NO_MEM;
+ }
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_gpiote(pin));
+ if (pin_in_use_by_port(pin))
+ {
+ uint8_t pin_and_sense = (uint8_t)
+ m_cb.port_handlers_pins[channel_port_get(pin) - GPIOTE_CH_NUM];
+ nrf_gpiote_polarity_t polarity =
+ (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
+ nrf_gpio_pin_sense_t sense;
+ if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
+ {
+ /* read current pin state and set for next sense to oposit */
+ sense = (nrf_gpio_pin_read(pin)) ?
+ NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
+ }
+ else
+ {
+ sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
+ NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
+ }
+ nrf_gpio_cfg_sense_set(pin, sense);
+ }
+ else if (pin_in_use_by_te(pin))
+ {
+ int32_t channel = (int32_t)channel_port_get(pin);
+ nrf_gpiote_events_t event = TE_IDX_TO_EVENT_ADDR((uint32_t)channel);
+
+ nrf_gpiote_event_enable((uint32_t)channel);
+
+ nrf_gpiote_event_clear(event);
+ if (int_enable)
+ {
+ nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
+ // Enable the interrupt only if event handler was provided.
+ if (handler)
+ {
+ nrf_gpiote_int_enable(1 << channel);
+ }
+ }
+ }
+}
+
+
+void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_gpiote(pin));
+ if (pin_in_use_by_port(pin))
+ {
+ nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
+ }
+ else if (pin_in_use_by_te(pin))
+ {
+ int32_t channel = (int32_t)channel_port_get(pin);
+ nrf_gpiote_event_disable((uint32_t)channel);
+ nrf_gpiote_int_disable(1 << channel);
+ }
+}
+
+
+void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_gpiote(pin));
+ nrfx_gpiote_in_event_disable(pin);
+ if (pin_in_use_by_te(pin))
+ {
+ nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
+ }
+ if (pin_configured_check(pin))
+ {
+ nrf_gpio_cfg_default(pin);
+ pin_configured_clear(pin);
+ }
+ channel_free((uint8_t)channel_port_get(pin));
+ pin_in_use_clear(pin);
+}
+
+
+bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ return nrf_gpio_pin_read(pin) ? true : false;
+}
+
+
+uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)
+{
+ NRFX_ASSERT(pin < NUMBER_OF_PINS);
+ NRFX_ASSERT(pin_in_use_by_port(pin) || pin_in_use_by_te(pin));
+
+ nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_PORT;
+
+ if (pin_in_use_by_te(pin))
+ {
+ event = TE_IDX_TO_EVENT_ADDR((uint32_t)channel_port_get(pin));
+ }
+ return nrf_gpiote_event_addr_get(event);
+}
+
+
+void nrfx_gpiote_irq_handler(void)
+{
+ uint32_t status = 0;
+ uint32_t input[GPIO_COUNT] = {0};
+
+ /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
+ uint32_t i;
+ nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
+ uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
+
+ for (i = 0; i < GPIOTE_CH_NUM; i++)
+ {
+ if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))
+ {
+ nrf_gpiote_event_clear(event);
+ status |= mask;
+ }
+ mask <<= 1;
+ /* Incrementing to next event, utilizing the fact that events are grouped together
+ * in ascending order. */
+ event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t));
+ }
+
+ /* collect PORT status event, if event is set read pins state. Processing is postponed to the
+ * end of interrupt. */
+ if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
+ {
+ nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
+ status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
+ nrf_gpio_ports_read(0, GPIO_COUNT, input);
+ }
+
+ /* Process pin events. */
+ if (status & NRF_GPIOTE_INT_IN_MASK)
+ {
+ mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
+
+ for (i = 0; i < GPIOTE_CH_NUM; i++)
+ {
+ if (mask & status)
+ {
+ nrfx_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
+ NRFX_LOG_DEBUG("Event in number: %d.", i);
+ nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
+ nrfx_gpiote_evt_handler_t handler = channel_handler_get(i);
+ NRFX_LOG_DEBUG("Pin: %d, polarity: %d.", pin, polarity);
+ if (handler)
+ {
+ handler(pin, polarity);
+ }
+ }
+ mask <<= 1;
+ }
+ }
+
+ if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
+ {
+ /* Process port event. */
+ uint32_t port_idx;
+ uint8_t repeat = 0;
+ uint32_t toggle_mask[GPIO_COUNT] = {0};
+ uint32_t pins_to_check[GPIO_COUNT];
+
+ // Faster way of doing memset because in interrupt context.
+ for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
+ {
+ pins_to_check[port_idx] = 0xFFFFFFFF;
+ }
+
+ do
+ {
+ repeat = 0;
+
+ for (i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
+ {
+ uint8_t pin_and_sense = (uint8_t)m_cb.port_handlers_pins[i];
+ nrfx_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
+
+ if ((m_cb.port_handlers_pins[i] != PIN_NOT_USED)
+ && nrf_bitmask_bit_is_set(pin, pins_to_check))
+ {
+ nrf_gpiote_polarity_t polarity =
+ (nrf_gpiote_polarity_t)((pin_and_sense &
+ SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
+ nrfx_gpiote_evt_handler_t handler =
+ channel_handler_get((uint32_t)channel_port_get(pin));
+ if (handler || (polarity == NRF_GPIOTE_POLARITY_TOGGLE))
+ {
+ if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
+ {
+ nrf_bitmask_bit_set(pin, toggle_mask);
+ }
+ nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
+ uint32_t pin_state = nrf_bitmask_bit_is_set(pin, input);
+ if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
+ (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) )
+ {
+ NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
+ if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
+ {
+ nrf_gpio_pin_sense_t next_sense =
+ (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
+ NRF_GPIO_PIN_SENSE_LOW :
+ NRF_GPIO_PIN_SENSE_HIGH;
+ nrf_gpio_cfg_sense_set(pin, next_sense);
+ ++repeat;
+
+ }
+ if (handler)
+ {
+ handler(pin, polarity);
+ }
+ }
+ }
+ }
+ }
+
+ if (repeat)
+ {
+ // When one of the pins in low-accuracy and toggle mode becomes active,
+ // it's sense mode is inverted to clear the internal SENSE signal.
+ // State of any other enabled low-accuracy input in toggle mode must be checked
+ // explicitly, because it does not trigger the interrput when SENSE signal is active.
+ // For more information about SENSE functionality, refer to Product Specification.
+
+ uint32_t new_input[GPIO_COUNT];
+ bool input_unchanged = true;
+ nrf_gpio_ports_read(0, GPIO_COUNT, new_input);
+
+ // Faster way of doing memcmp because in interrupt context.
+ for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
+ {
+ if (new_input[port_idx] != input[port_idx])
+ {
+ input_unchanged = false;
+ break;
+ }
+ }
+
+ if (input_unchanged)
+ {
+ // No change.
+ repeat = 0;
+ }
+ else
+ {
+ // Faster way of doing memcpy because in interrupt context.
+ for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
+ {
+ input[port_idx] = new_input[port_idx];
+ pins_to_check[port_idx] = toggle_mask[port_idx];
+ }
+ }
+ }
+ }
+ while (repeat);
+ }
+}
+
+
+/*lint -restore*/
+#endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_i2s.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_i2s.c
new file mode 100644
index 0000000..35beaab
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_i2s.c
@@ -0,0 +1,420 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_I2S_ENABLED)
+
+#include <nrfx_i2s.h>
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE I2S
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_I2S_EVENT_RXPTRUPD ? "NRF_I2S_EVENT_RXPTRUPD" : \
+ (event == NRF_I2S_EVENT_TXPTRUPD ? "NRF_I2S_EVENT_TXPTRUPD" : \
+ (event == NRF_I2S_EVENT_STOPPED ? "NRF_I2S_EVENT_STOPPED" : \
+ "UNKNOWN EVENT")))
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_i2s_data_handler_t handler;
+ nrfx_drv_state_t state;
+
+ bool use_rx : 1;
+ bool use_tx : 1;
+ bool rx_ready : 1;
+ bool tx_ready : 1;
+ bool buffers_needed : 1;
+ bool buffers_reused : 1;
+
+ uint16_t buffer_size;
+ nrfx_i2s_buffers_t next_buffers;
+ nrfx_i2s_buffers_t current_buffers;
+} i2s_control_block_t;
+static i2s_control_block_t m_cb;
+
+
+static void configure_pins(nrfx_i2s_config_t const * p_config)
+{
+ uint32_t mck_pin, sdout_pin, sdin_pin;
+
+ // Configure pins used by the peripheral:
+
+ // - SCK and LRCK (required) - depending on the mode of operation these
+ // pins are configured as outputs (in Master mode) or inputs (in Slave
+ // mode).
+ if (p_config->mode == NRF_I2S_MODE_MASTER)
+ {
+ nrf_gpio_cfg_output(p_config->sck_pin);
+ nrf_gpio_cfg_output(p_config->lrck_pin);
+ }
+ else
+ {
+ nrf_gpio_cfg_input(p_config->sck_pin, NRF_GPIO_PIN_NOPULL);
+ nrf_gpio_cfg_input(p_config->lrck_pin, NRF_GPIO_PIN_NOPULL);
+ }
+
+ // - MCK (optional) - always output,
+ if (p_config->mck_pin != NRFX_I2S_PIN_NOT_USED)
+ {
+ mck_pin = p_config->mck_pin;
+ nrf_gpio_cfg_output(mck_pin);
+ }
+ else
+ {
+ mck_pin = NRF_I2S_PIN_NOT_CONNECTED;
+ }
+
+ // - SDOUT (optional) - always output,
+ if (p_config->sdout_pin != NRFX_I2S_PIN_NOT_USED)
+ {
+ sdout_pin = p_config->sdout_pin;
+ nrf_gpio_cfg_output(sdout_pin);
+ }
+ else
+ {
+ sdout_pin = NRF_I2S_PIN_NOT_CONNECTED;
+ }
+
+ // - SDIN (optional) - always input.
+ if (p_config->sdin_pin != NRFX_I2S_PIN_NOT_USED)
+ {
+ sdin_pin = p_config->sdin_pin;
+ nrf_gpio_cfg_input(sdin_pin, NRF_GPIO_PIN_NOPULL);
+ }
+ else
+ {
+ sdin_pin = NRF_I2S_PIN_NOT_CONNECTED;
+ }
+
+ nrf_i2s_pins_set(NRF_I2S,
+ p_config->sck_pin,
+ p_config->lrck_pin,
+ mck_pin,
+ sdout_pin,
+ sdin_pin);
+}
+
+
+nrfx_err_t nrfx_i2s_init(nrfx_i2s_config_t const * p_config,
+ nrfx_i2s_data_handler_t handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(handler);
+
+ nrfx_err_t err_code;
+
+ if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (!nrf_i2s_configure(NRF_I2S,
+ p_config->mode,
+ p_config->format,
+ p_config->alignment,
+ p_config->sample_width,
+ p_config->channels,
+ p_config->mck_setup,
+ p_config->ratio))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ configure_pins(p_config);
+
+ m_cb.handler = handler;
+
+ NRFX_IRQ_PRIORITY_SET(I2S_IRQn, p_config->irq_priority);
+ NRFX_IRQ_ENABLE(I2S_IRQn);
+
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+
+ NRFX_LOG_INFO("Initialized.");
+ return NRFX_SUCCESS;
+}
+
+
+void nrfx_i2s_uninit(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrfx_i2s_stop();
+
+ NRFX_IRQ_DISABLE(I2S_IRQn);
+
+ nrf_i2s_pins_set(NRF_I2S,
+ NRF_I2S_PIN_NOT_CONNECTED,
+ NRF_I2S_PIN_NOT_CONNECTED,
+ NRF_I2S_PIN_NOT_CONNECTED,
+ NRF_I2S_PIN_NOT_CONNECTED,
+ NRF_I2S_PIN_NOT_CONNECTED);
+
+ m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+
+nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers,
+ uint16_t buffer_size,
+ uint8_t flags)
+{
+ NRFX_ASSERT(p_initial_buffers != NULL);
+ NRFX_ASSERT(p_initial_buffers->p_rx_buffer != NULL ||
+ p_initial_buffers->p_tx_buffer != NULL);
+ NRFX_ASSERT(buffer_size != 0);
+ (void)(flags);
+
+ nrfx_err_t err_code;
+
+ if (m_cb.state != NRFX_DRV_STATE_INITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (((p_initial_buffers->p_rx_buffer != NULL)
+ && !nrfx_is_in_ram(p_initial_buffers->p_rx_buffer))
+ ||
+ ((p_initial_buffers->p_tx_buffer != NULL)
+ && !nrfx_is_in_ram(p_initial_buffers->p_tx_buffer)))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_cb.use_rx = (p_initial_buffers->p_rx_buffer != NULL);
+ m_cb.use_tx = (p_initial_buffers->p_tx_buffer != NULL);
+ m_cb.rx_ready = false;
+ m_cb.tx_ready = false;
+ m_cb.buffers_needed = false;
+ m_cb.buffer_size = buffer_size;
+
+ // Set the provided initial buffers as next, they will become the current
+ // ones after the IRQ handler is called for the first time, what will occur
+ // right after the START task is triggered.
+ m_cb.next_buffers = *p_initial_buffers;
+ m_cb.current_buffers.p_rx_buffer = NULL;
+ m_cb.current_buffers.p_tx_buffer = NULL;
+
+ nrf_i2s_transfer_set(NRF_I2S,
+ m_cb.buffer_size,
+ m_cb.next_buffers.p_rx_buffer,
+ m_cb.next_buffers.p_tx_buffer);
+
+ nrf_i2s_enable(NRF_I2S);
+
+ m_cb.state = NRFX_DRV_STATE_POWERED_ON;
+
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD);
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD);
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_STOPPED);
+ nrf_i2s_int_enable(NRF_I2S, (m_cb.use_rx ? NRF_I2S_INT_RXPTRUPD_MASK : 0) |
+ (m_cb.use_tx ? NRF_I2S_INT_TXPTRUPD_MASK : 0) |
+ NRF_I2S_INT_STOPPED_MASK);
+ nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_START);
+
+ NRFX_LOG_INFO("Started.");
+ return NRFX_SUCCESS;
+}
+
+
+nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers)
+{
+ NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_POWERED_ON);
+ NRFX_ASSERT(p_buffers);
+
+ nrfx_err_t err_code;
+
+ if (!m_cb.buffers_needed)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (((p_buffers->p_rx_buffer != NULL)
+ && !nrfx_is_in_ram(p_buffers->p_rx_buffer))
+ ||
+ ((p_buffers->p_tx_buffer != NULL)
+ && !nrfx_is_in_ram(p_buffers->p_tx_buffer)))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (m_cb.use_tx)
+ {
+ NRFX_ASSERT(p_buffers->p_tx_buffer != NULL);
+ nrf_i2s_tx_buffer_set(NRF_I2S, p_buffers->p_tx_buffer);
+ }
+ if (m_cb.use_rx)
+ {
+ NRFX_ASSERT(p_buffers->p_rx_buffer != NULL);
+ nrf_i2s_rx_buffer_set(NRF_I2S, p_buffers->p_rx_buffer);
+ }
+
+ m_cb.next_buffers = *p_buffers;
+ m_cb.buffers_needed = false;
+
+ return NRFX_SUCCESS;
+}
+
+
+void nrfx_i2s_stop(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ m_cb.buffers_needed = false;
+
+ // First disable interrupts, then trigger the STOP task, so no spurious
+ // RXPTRUPD and TXPTRUPD events (see nRF52 anomaly 55) are processed.
+ nrf_i2s_int_disable(NRF_I2S, NRF_I2S_INT_RXPTRUPD_MASK |
+ NRF_I2S_INT_TXPTRUPD_MASK);
+ nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_STOP);
+}
+
+
+void nrfx_i2s_irq_handler(void)
+{
+ if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD))
+ {
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD);
+ m_cb.tx_ready = true;
+ if (m_cb.use_tx && m_cb.buffers_needed)
+ {
+ m_cb.buffers_reused = true;
+ }
+ }
+ if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD))
+ {
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD);
+ m_cb.rx_ready = true;
+ if (m_cb.use_rx && m_cb.buffers_needed)
+ {
+ m_cb.buffers_reused = true;
+ }
+ }
+
+ if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_STOPPED))
+ {
+ nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_STOPPED);
+ nrf_i2s_int_disable(NRF_I2S, NRF_I2S_INT_STOPPED_MASK);
+ nrf_i2s_disable(NRF_I2S);
+
+ // When stopped, release all buffers, including these scheduled for
+ // the next transfer.
+ m_cb.handler(&m_cb.current_buffers, 0);
+ m_cb.handler(&m_cb.next_buffers, 0);
+
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Stopped.");
+ }
+ else
+ {
+ // Check if the requested transfer has been completed:
+ // - full-duplex mode
+ if ((m_cb.use_tx && m_cb.use_rx && m_cb.tx_ready && m_cb.rx_ready) ||
+ // - TX only mode
+ (!m_cb.use_rx && m_cb.tx_ready) ||
+ // - RX only mode
+ (!m_cb.use_tx && m_cb.rx_ready))
+ {
+ m_cb.tx_ready = false;
+ m_cb.rx_ready = false;
+
+ // If the application did not supply the buffers for the next
+ // part of the transfer until this moment, the current buffers
+ // cannot be released, since the I2S peripheral already started
+ // using them. Signal this situation to the application by
+ // passing NULL instead of the structure with released buffers.
+ if (m_cb.buffers_reused)
+ {
+ m_cb.buffers_reused = false;
+ // This will most likely be set at this point. However, there is
+ // a small time window between TXPTRUPD and RXPTRUPD events,
+ // and it is theoretically possible that next buffers will be
+ // set in this window, so to be sure this flag is set to true,
+ // set it explicitly.
+ m_cb.buffers_needed = true;
+ m_cb.handler(NULL,
+ NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED);
+ }
+ else
+ {
+ // Buffers that have been used by the I2S peripheral (current)
+ // are now released and will be returned to the application,
+ // and the ones scheduled to be used as next become the current
+ // ones.
+ nrfx_i2s_buffers_t released_buffers = m_cb.current_buffers;
+ m_cb.current_buffers = m_cb.next_buffers;
+ m_cb.next_buffers.p_rx_buffer = NULL;
+ m_cb.next_buffers.p_tx_buffer = NULL;
+ m_cb.buffers_needed = true;
+ m_cb.handler(&released_buffers,
+ NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED);
+ }
+
+ }
+ }
+}
+
+#endif // NRFX_CHECK(NRFX_I2S_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_lpcomp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_lpcomp.c
new file mode 100644
index 0000000..024eda6
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_lpcomp.c
@@ -0,0 +1,174 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_LPCOMP_ENABLED)
+
+#include <nrfx_lpcomp.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE LPCOMP
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_LPCOMP_EVENT_READY ? "NRF_LPCOMP_EVENT_READY" : \
+ (event == NRF_LPCOMP_EVENT_DOWN ? "NRF_LPCOMP_EVENT_DOWN" : \
+ (event == NRF_LPCOMP_EVENT_UP ? "NRF_LPCOMP_EVENT_UP" : \
+ (event == NRF_LPCOMP_EVENT_CROSS ? "NRF_LPCOMP_EVENT_CROSS" : \
+ "UNKNOWN EVENT"))))
+
+
+static nrfx_lpcomp_event_handler_t m_lpcomp_event_handler = NULL;
+static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
+
+static void lpcomp_execute_handler(nrf_lpcomp_event_t event, uint32_t event_mask)
+{
+ if (nrf_lpcomp_event_check(event) && nrf_lpcomp_int_enable_check(event_mask))
+ {
+ nrf_lpcomp_event_clear(event);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
+
+ m_lpcomp_event_handler(event);
+ }
+}
+
+void nrfx_lpcomp_irq_handler(void)
+{
+ lpcomp_execute_handler(NRF_LPCOMP_EVENT_READY, LPCOMP_INTENSET_READY_Msk);
+ lpcomp_execute_handler(NRF_LPCOMP_EVENT_DOWN, LPCOMP_INTENSET_DOWN_Msk);
+ lpcomp_execute_handler(NRF_LPCOMP_EVENT_UP, LPCOMP_INTENSET_UP_Msk);
+ lpcomp_execute_handler(NRF_LPCOMP_EVENT_CROSS, LPCOMP_INTENSET_CROSS_Msk);
+}
+
+nrfx_err_t nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,
+ nrfx_lpcomp_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ nrfx_err_t err_code;
+
+ if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
+ { // LPCOMP driver is already initialized
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_lpcomp_event_handler = event_handler;
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ if (nrfx_prs_acquire(NRF_LPCOMP, nrfx_lpcomp_irq_handler) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif
+
+ nrf_lpcomp_configure(&(p_config->hal));
+
+ nrf_lpcomp_input_select(p_config->input);
+
+ switch (p_config->hal.detection)
+ {
+ case NRF_LPCOMP_DETECT_UP:
+ nrf_lpcomp_int_enable(LPCOMP_INTENSET_UP_Msk);
+ break;
+
+ case NRF_LPCOMP_DETECT_DOWN:
+ nrf_lpcomp_int_enable(LPCOMP_INTENSET_DOWN_Msk);
+ break;
+
+ case NRF_LPCOMP_DETECT_CROSS:
+ nrf_lpcomp_int_enable(LPCOMP_INTENSET_CROSS_Msk);
+ break;
+
+ default:
+ break;
+ }
+ nrf_lpcomp_shorts_enable(NRF_LPCOMP_SHORT_READY_SAMPLE_MASK);
+
+ NRFX_IRQ_PRIORITY_SET(LPCOMP_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(LPCOMP_IRQn);
+
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_lpcomp_uninit(void)
+{
+ NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_IRQ_DISABLE(LPCOMP_IRQn);
+ nrfx_lpcomp_disable();
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(NRF_LPCOMP);
+#endif
+ m_state = NRFX_DRV_STATE_UNINITIALIZED;
+ m_lpcomp_event_handler = NULL;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_lpcomp_enable(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_lpcomp_enable();
+ nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_START);
+ m_state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled.");
+}
+
+void nrfx_lpcomp_disable(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_lpcomp_disable();
+ nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_STOP);
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled.");
+}
+
+#endif // NRFX_CHECK(NRFX_LPCOMP_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pdm.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pdm.c
new file mode 100644
index 0000000..db0945e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pdm.c
@@ -0,0 +1,370 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_PDM_ENABLED)
+
+#include <nrfx_pdm.h>
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE PDM
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_PDM_EVENT_STARTED ? "NRF_PDM_EVENT_STARTED" : \
+ (event == NRF_PDM_EVENT_STOPPED ? "NRF_PDM_EVENT_STOPPED" : \
+ (event == NRF_PDM_EVENT_END ? "NRF_PDM_EVENT_END" : \
+ "UNKNOWN EVENT")))
+
+
+/** @brief PDM interface status. */
+typedef enum
+{
+ NRFX_PDM_STATE_IDLE,
+ NRFX_PDM_STATE_RUNNING,
+ NRFX_PDM_STATE_STARTING,
+ NRFX_PDM_STATE_STOPPING
+} nrfx_pdm_state_t;
+
+/** @brief PDM interface control block.*/
+typedef struct
+{
+ nrfx_pdm_event_handler_t event_handler; ///< Event handler function pointer.
+ int16_t * buff_address[2]; ///< Sample buffers.
+ uint16_t buff_length[2]; ///< Length of the sample buffers.
+ nrfx_drv_state_t drv_state; ///< Driver state.
+ volatile nrfx_pdm_state_t op_state; ///< PDM peripheral operation state.
+ uint8_t active_buffer; ///< Number of currently active buffer.
+ uint8_t error; ///< Driver error flag.
+ volatile uint8_t irq_buff_request; ///< Request the next buffer in the ISR.
+} nrfx_pdm_cb_t;
+
+static nrfx_pdm_cb_t m_cb;
+
+
+void nrfx_pdm_irq_handler(void)
+{
+ if (nrf_pdm_event_check(NRF_PDM_EVENT_STARTED))
+ {
+ nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STARTED));
+
+ uint8_t finished_buffer = m_cb.active_buffer;
+
+ // Check if the next buffer was set before.
+ uint8_t next_buffer = (~m_cb.active_buffer) & 0x01;
+ if (m_cb.buff_address[next_buffer] ||
+ m_cb.op_state == NRFX_PDM_STATE_STARTING)
+ {
+ nrfx_pdm_evt_t evt;
+ evt.error = NRFX_PDM_NO_ERROR;
+ m_cb.error = 0;
+
+ // Release the full buffer if ready and request the next one.
+ if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
+ {
+ evt.buffer_released = 0;
+ m_cb.op_state = NRFX_PDM_STATE_RUNNING;
+ }
+ else
+ {
+ evt.buffer_released = m_cb.buff_address[finished_buffer];
+ m_cb.buff_address[finished_buffer] = 0;
+ m_cb.active_buffer = next_buffer;
+ }
+ evt.buffer_requested = true;
+ m_cb.event_handler(&evt);
+ }
+ else
+ {
+ // No next buffer available. Report an error.
+ // Do not request the new buffer as it was already done.
+ if (m_cb.error == 0)
+ {
+ nrfx_pdm_evt_t const evt = {
+ .buffer_requested = false,
+ .buffer_released = NULL,
+ .error = NRFX_PDM_ERROR_OVERFLOW
+ };
+ m_cb.error = 1;
+ m_cb.event_handler(&evt);
+ }
+ }
+
+ if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
+ {
+ m_cb.op_state = NRFX_PDM_STATE_RUNNING;
+ }
+ }
+ else if (nrf_pdm_event_check(NRF_PDM_EVENT_STOPPED))
+ {
+ nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STOPPED));
+ nrf_pdm_disable();
+ m_cb.op_state = NRFX_PDM_STATE_IDLE;
+
+ // Release the buffers.
+ nrfx_pdm_evt_t evt;
+ evt.error = NRFX_PDM_NO_ERROR;
+ evt.buffer_requested = false;
+ if (m_cb.buff_address[m_cb.active_buffer])
+ {
+ evt.buffer_released = m_cb.buff_address[m_cb.active_buffer];
+ m_cb.buff_address[m_cb.active_buffer] = 0;
+ m_cb.event_handler(&evt);
+ }
+
+ uint8_t second_buffer = (~m_cb.active_buffer) & 0x01;
+ if (m_cb.buff_address[second_buffer])
+ {
+ evt.buffer_released = m_cb.buff_address[second_buffer];
+ m_cb.buff_address[second_buffer] = 0;
+ m_cb.event_handler(&evt);
+ }
+ m_cb.active_buffer = 0;
+ }
+
+ if (m_cb.irq_buff_request)
+ {
+ nrfx_pdm_evt_t const evt =
+ {
+ .buffer_requested = true,
+ .buffer_released = NULL,
+ .error = NRFX_PDM_NO_ERROR,
+ };
+ m_cb.irq_buff_request = 0;
+ m_cb.event_handler(&evt);
+ }
+}
+
+
+nrfx_err_t nrfx_pdm_init(nrfx_pdm_config_t const * p_config,
+ nrfx_pdm_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ nrfx_err_t err_code;
+
+ if (m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (p_config->gain_l > NRF_PDM_GAIN_MAXIMUM ||
+ p_config->gain_r > NRF_PDM_GAIN_MAXIMUM)
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_cb.buff_address[0] = 0;
+ m_cb.buff_address[1] = 0;
+ m_cb.active_buffer = 0;
+ m_cb.error = 0;
+ m_cb.event_handler = event_handler;
+ m_cb.op_state = NRFX_PDM_STATE_IDLE;
+
+ nrf_pdm_clock_set(p_config->clock_freq);
+ nrf_pdm_mode_set(p_config->mode, p_config->edge);
+ nrf_pdm_gain_set(p_config->gain_l, p_config->gain_r);
+
+ nrf_gpio_cfg_output(p_config->pin_clk);
+ nrf_gpio_pin_clear(p_config->pin_clk);
+ nrf_gpio_cfg_input(p_config->pin_din, NRF_GPIO_PIN_NOPULL);
+ nrf_pdm_psel_connect(p_config->pin_clk, p_config->pin_din);
+
+ nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
+ nrf_pdm_event_clear(NRF_PDM_EVENT_END);
+ nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED);
+ nrf_pdm_int_enable(NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED);
+ NRFX_IRQ_PRIORITY_SET(PDM_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(PDM_IRQn);
+ m_cb.drv_state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_pdm_uninit(void)
+{
+ nrf_pdm_disable();
+ nrf_pdm_psel_disconnect();
+ m_cb.drv_state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+static void pdm_start()
+{
+ m_cb.drv_state = NRFX_DRV_STATE_POWERED_ON;
+ nrf_pdm_enable();
+ nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
+ nrf_pdm_task_trigger(NRF_PDM_TASK_START);
+}
+
+static void pdm_buf_request()
+{
+ m_cb.irq_buff_request = 1;
+ NRFX_IRQ_PENDING_SET(PDM_IRQn);
+}
+
+nrfx_err_t nrfx_pdm_start(void)
+{
+ NRFX_ASSERT(m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrfx_err_t err_code;
+
+ if (m_cb.op_state != NRFX_PDM_STATE_IDLE)
+ {
+ if (m_cb.op_state == NRFX_PDM_STATE_RUNNING)
+ {
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_cb.op_state = NRFX_PDM_STATE_STARTING;
+ pdm_buf_request();
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length)
+{
+ if (m_cb.drv_state == NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ return NRFX_ERROR_INVALID_STATE;
+ }
+ if (m_cb.op_state == NRFX_PDM_STATE_STOPPING)
+ {
+ return NRFX_ERROR_BUSY;
+ }
+ if ((buffer == NULL) || (buffer_length > NRFX_PDM_MAX_BUFFER_SIZE))
+ {
+ return NRFX_ERROR_INVALID_PARAM;
+ }
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ // Enter the PDM critical section.
+ NRFX_IRQ_DISABLE(PDM_IRQn);
+
+ uint8_t next_buffer = (~m_cb.active_buffer) & 0x01;
+ if (m_cb.op_state == NRFX_PDM_STATE_STARTING)
+ {
+ next_buffer = 0;
+ }
+
+ if (m_cb.buff_address[next_buffer])
+ {
+ // Buffer already set.
+ err_code = NRFX_ERROR_BUSY;
+ }
+ else
+ {
+ m_cb.buff_address[next_buffer] = buffer;
+ m_cb.buff_length[next_buffer] = buffer_length;
+ nrf_pdm_buffer_set((uint32_t *)buffer, buffer_length);
+
+ if (m_cb.drv_state != NRFX_DRV_STATE_POWERED_ON)
+ {
+ pdm_start();
+ }
+ }
+
+ NRFX_IRQ_ENABLE(PDM_IRQn);
+ return err_code;
+}
+
+nrfx_err_t nrfx_pdm_stop(void)
+{
+ NRFX_ASSERT(m_cb.drv_state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrfx_err_t err_code;
+
+ if (m_cb.op_state != NRFX_PDM_STATE_RUNNING)
+ {
+ if (m_cb.op_state == NRFX_PDM_STATE_IDLE ||
+ m_cb.op_state == NRFX_PDM_STATE_STARTING)
+ {
+ nrf_pdm_disable();
+ m_cb.op_state = NRFX_PDM_STATE_IDLE;
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ m_cb.drv_state = NRFX_DRV_STATE_INITIALIZED;
+ m_cb.op_state = NRFX_PDM_STATE_STOPPING;
+
+ nrf_pdm_task_trigger(NRF_PDM_TASK_STOP);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+#endif // NRFX_CHECK(NRFX_PDM_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power.c
new file mode 100644
index 0000000..d861951
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power.c
@@ -0,0 +1,306 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_POWER_ENABLED)
+
+#include <nrfx_power.h>
+
+#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
+extern bool nrfx_clock_irq_enabled;
+#endif
+
+/**
+ * @internal
+ * @defgroup nrfx_power_internals POWER driver internals
+ * @ingroup nrfx_power
+ *
+ * Internal variables, auxiliary macros and functions of POWER driver.
+ * @{
+ */
+
+/**
+ * This variable is used to check whether common POWER_CLOCK common interrupt
+ * should be disabled or not if @ref nrfx_clock tries to disable the interrupt.
+ */
+
+bool nrfx_power_irq_enabled;
+
+/**
+ * @brief The initialization flag
+ */
+
+#define m_initialized nrfx_power_irq_enabled
+
+/**
+ * @brief The handler of power fail comparator warning event
+ */
+static nrfx_power_pofwarn_event_handler_t m_pofwarn_handler;
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief The handler of sleep event handler
+ */
+static nrfx_power_sleep_event_handler_t m_sleepevt_handler;
+#endif
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief The handler of USB power events
+ */
+static nrfx_power_usb_event_handler_t m_usbevt_handler;
+#endif
+
+/** @} */
+
+nrfx_power_pofwarn_event_handler_t nrfx_power_pof_handler_get(void)
+{
+ return m_pofwarn_handler;
+}
+
+#if NRF_POWER_HAS_USBREG
+nrfx_power_usb_event_handler_t nrfx_power_usb_handler_get(void)
+{
+ return m_usbevt_handler;
+}
+#endif
+
+nrfx_err_t nrfx_power_init(nrfx_power_config_t const * p_config)
+{
+ NRFX_ASSERT(p_config);
+ if (m_initialized)
+ {
+ return NRFX_ERROR_ALREADY_INITIALIZED;
+ }
+
+#if NRF_POWER_HAS_VDDH
+ nrf_power_dcdcen_vddh_set(p_config->dcdcenhv);
+#endif
+ nrf_power_dcdcen_set(p_config->dcdcen);
+
+ nrfx_power_clock_irq_init();
+
+ m_initialized = true;
+ return NRFX_SUCCESS;
+}
+
+
+void nrfx_power_uninit(void)
+{
+ NRFX_ASSERT(m_initialized);
+
+#if NRFX_CHECK(NRFX_CLOCK_ENABLED)
+ if (!nrfx_clock_irq_enabled)
+#endif
+ {
+ NRFX_IRQ_DISABLE(POWER_CLOCK_IRQn);
+ }
+
+ nrfx_power_pof_uninit();
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+ nrfx_power_sleepevt_uninit();
+#endif
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+ nrfx_power_usbevt_uninit();
+#endif
+ m_initialized = false;
+}
+
+void nrfx_power_pof_init(nrfx_power_pofwarn_config_t const * p_config)
+{
+ NRFX_ASSERT(p_config != NULL);
+
+ nrfx_power_pof_uninit();
+
+ if (p_config->handler != NULL)
+ {
+ m_pofwarn_handler = p_config->handler;
+ }
+}
+
+void nrfx_power_pof_enable(nrfx_power_pofwarn_config_t const * p_config)
+{
+ nrf_power_pofcon_set(true, p_config->thr);
+#if NRF_POWER_HAS_VDDH || defined(__NRFX_DOXYGEN__)
+ nrf_power_pofcon_vddh_set(p_config->thrvddh);
+#endif
+ if (m_pofwarn_handler != NULL)
+ {
+ nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK);
+ }
+}
+
+void nrfx_power_pof_disable(void)
+{
+ nrf_power_int_disable(NRF_POWER_INT_POFWARN_MASK);
+}
+
+void nrfx_power_pof_uninit(void)
+{
+ m_pofwarn_handler = NULL;
+}
+
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+void nrfx_power_sleepevt_init(nrfx_power_sleepevt_config_t const * p_config)
+{
+ NRFX_ASSERT(p_config != NULL);
+
+ nrfx_power_sleepevt_uninit();
+ if (p_config->handler != NULL)
+ {
+ m_sleepevt_handler = p_config->handler;
+ }
+}
+
+void nrfx_power_sleepevt_enable(nrfx_power_sleepevt_config_t const * p_config)
+{
+ uint32_t enmask = 0;
+ if (p_config->en_enter)
+ {
+ enmask |= NRF_POWER_INT_SLEEPENTER_MASK;
+ nrf_power_event_clear(NRF_POWER_EVENT_SLEEPENTER);
+ }
+ if (p_config->en_exit)
+ {
+ enmask |= NRF_POWER_INT_SLEEPEXIT_MASK;
+ nrf_power_event_clear(NRF_POWER_EVENT_SLEEPEXIT);
+ }
+ nrf_power_int_enable(enmask);
+}
+
+void nrfx_power_sleepevt_disable(void)
+{
+ nrf_power_int_disable(
+ NRF_POWER_INT_SLEEPENTER_MASK |
+ NRF_POWER_INT_SLEEPEXIT_MASK);
+}
+
+void nrfx_power_sleepevt_uninit(void)
+{
+ m_sleepevt_handler = NULL;
+}
+#endif /* NRF_POWER_HAS_SLEEPEVT */
+
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+void nrfx_power_usbevt_init(nrfx_power_usbevt_config_t const * p_config)
+{
+ nrfx_power_usbevt_uninit();
+ if (p_config->handler != NULL)
+ {
+ m_usbevt_handler = p_config->handler;
+ }
+}
+
+void nrfx_power_usbevt_enable(void)
+{
+ nrf_power_int_enable(
+ NRF_POWER_INT_USBDETECTED_MASK |
+ NRF_POWER_INT_USBREMOVED_MASK |
+ NRF_POWER_INT_USBPWRRDY_MASK);
+}
+
+void nrfx_power_usbevt_disable(void)
+{
+ nrf_power_int_disable(
+ NRF_POWER_INT_USBDETECTED_MASK |
+ NRF_POWER_INT_USBREMOVED_MASK |
+ NRF_POWER_INT_USBPWRRDY_MASK);
+}
+
+void nrfx_power_usbevt_uninit(void)
+{
+ m_usbevt_handler = NULL;
+}
+#endif /* NRF_POWER_HAS_USBREG */
+
+
+void nrfx_power_irq_handler(void)
+{
+ uint32_t enabled = nrf_power_int_enable_get();
+ if ((0 != (enabled & NRF_POWER_INT_POFWARN_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_POFWARN))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_pofwarn_handler != NULL);
+ m_pofwarn_handler();
+ }
+#if NRF_POWER_HAS_SLEEPEVT || defined(__NRFX_DOXYGEN__)
+ if ((0 != (enabled & NRF_POWER_INT_SLEEPENTER_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPENTER))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_sleepevt_handler != NULL);
+ m_sleepevt_handler(NRFX_POWER_SLEEP_EVT_ENTER);
+ }
+ if ((0 != (enabled & NRF_POWER_INT_SLEEPEXIT_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPEXIT))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_sleepevt_handler != NULL);
+ m_sleepevt_handler(NRFX_POWER_SLEEP_EVT_EXIT);
+ }
+#endif
+#if NRF_POWER_HAS_USBREG || defined(__NRFX_DOXYGEN__)
+ if ((0 != (enabled & NRF_POWER_INT_USBDETECTED_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBDETECTED))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_usbevt_handler != NULL);
+ m_usbevt_handler(NRFX_POWER_USB_EVT_DETECTED);
+ }
+ if ((0 != (enabled & NRF_POWER_INT_USBREMOVED_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBREMOVED))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_usbevt_handler != NULL);
+ m_usbevt_handler(NRFX_POWER_USB_EVT_REMOVED);
+ }
+ if ((0 != (enabled & NRF_POWER_INT_USBPWRRDY_MASK)) &&
+ nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBPWRRDY))
+ {
+ /* Cannot be null if event is enabled */
+ NRFX_ASSERT(m_usbevt_handler != NULL);
+ m_usbevt_handler(NRFX_POWER_USB_EVT_READY);
+ }
+#endif
+}
+
+#endif // NRFX_CHECK(NRFX_POWER_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power_clock.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power_clock.c
new file mode 100644
index 0000000..ff69bf7
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_power_clock.c
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+#include <nrfx_power.h>
+#include <nrfx_clock.h>
+
+
+#if NRFX_CHECK(NRFX_POWER_ENABLED) && NRFX_CHECK(NRFX_CLOCK_ENABLED)
+void nrfx_power_clock_irq_handler(void)
+{
+ nrfx_power_irq_handler();
+ nrfx_clock_irq_handler();
+}
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_ppi.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_ppi.c
new file mode 100644
index 0000000..067ba18
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_ppi.c
@@ -0,0 +1,534 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_PPI_ENABLED)
+
+#include <nrfx_ppi.h>
+
+#define NRFX_LOG_MODULE_NAME PPI
+#include <nrfx_log.h>
+
+
+static uint32_t m_channels_allocated; /**< Bitmap representing channels availability. 1 when a channel is allocated, 0 otherwise. */
+static uint8_t m_groups_allocated; /**< Bitmap representing groups availability. 1 when a group is allocated, 0 otherwise.*/
+
+
+/**
+ * @brief Compute a group mask (needed for driver internals, not used for NRF_PPI registers).
+ *
+ * @param[in] group Group number to transform to a mask.
+ *
+ * @retval Group mask.
+ */
+__STATIC_INLINE uint32_t group_to_mask(nrf_ppi_channel_group_t group)
+{
+ return (1uL << (uint32_t) group);
+}
+
+
+/**
+ * @brief Check whether a channel is a programmable channel and can be used by an application.
+ *
+ * @param[in] channel Channel to check.
+ *
+ * @retval true The channel is a programmable application channel.
+ * @retval false The channel is used by a stack (for example SoftDevice) or is preprogrammed.
+ */
+__STATIC_INLINE bool is_programmable_app_channel(nrf_ppi_channel_t channel)
+{
+ return ((NRFX_PPI_PROG_APP_CHANNELS_MASK & nrfx_ppi_channel_to_mask(channel)) != 0);
+}
+
+
+/**
+ * @brief Check whether channels can be used by an application.
+ *
+ * @param[in] channel_mask Channel mask to check.
+ *
+ * @retval true All specified channels can be used by an application.
+ * @retval false At least one specified channel is used by a stack (for example SoftDevice).
+ */
+__STATIC_INLINE bool are_app_channels(uint32_t channel_mask)
+{
+ //lint -e(587)
+ return ((~(NRFX_PPI_ALL_APP_CHANNELS_MASK) & channel_mask) == 0);
+}
+
+
+/**
+ * @brief Check whether a channel can be used by an application.
+ *
+ * @param[in] channel Channel to check.
+ *
+ * @retval true The channel can be used by an application.
+ * @retval false The channel is used by a stack (for example SoftDevice).
+ */
+__STATIC_INLINE bool is_app_channel(nrf_ppi_channel_t channel)
+{
+ return are_app_channels(nrfx_ppi_channel_to_mask(channel));
+}
+
+
+/**
+ * @brief Check whether a channel group can be used by an application.
+ *
+ * @param[in] group Group to check.
+ *
+ * @retval true The group is an application group.
+ * @retval false The group is not an application group (this group either does not exist or
+ * it is used by a stack (for example SoftDevice)).
+ */
+__STATIC_INLINE bool is_app_group(nrf_ppi_channel_group_t group)
+{
+ return ((NRFX_PPI_ALL_APP_GROUPS_MASK & group_to_mask(group)) != 0);
+}
+
+
+/**
+ * @brief Check whether a channel is allocated.
+ *
+ * @param[in] channel_num Channel number to check.
+ *
+ * @retval true The channel is allocated.
+ * @retval false The channel is not allocated.
+ */
+__STATIC_INLINE bool is_allocated_channel(nrf_ppi_channel_t channel)
+{
+ return ((m_channels_allocated & nrfx_ppi_channel_to_mask(channel)) != 0);
+}
+
+
+/**
+ * @brief Set channel allocated indication.
+ *
+ * @param[in] channel_num Specifies the channel to set the "allocated" indication.
+ */
+__STATIC_INLINE void channel_allocated_set(nrf_ppi_channel_t channel)
+{
+ m_channels_allocated |= nrfx_ppi_channel_to_mask(channel);
+}
+
+
+/**
+ * @brief Clear channel allocated indication.
+ *
+ * @param[in] channel_num Specifies the channel to clear the "allocated" indication.
+ */
+__STATIC_INLINE void channel_allocated_clr(nrf_ppi_channel_t channel)
+{
+ m_channels_allocated &= ~nrfx_ppi_channel_to_mask(channel);
+}
+
+
+/**
+ * @brief Clear all allocated channels.
+ */
+__STATIC_INLINE void channel_allocated_clr_all(void)
+{
+ m_channels_allocated &= ~NRFX_PPI_ALL_APP_CHANNELS_MASK;
+}
+
+
+/**
+ * @brief Check whether a group is allocated.
+ *
+ * @param[in] group_num Group number to check.
+ *
+ * @retval true The group is allocated.
+ * false The group is not allocated.
+ */
+__STATIC_INLINE bool is_allocated_group(nrf_ppi_channel_group_t group)
+{
+ return ((m_groups_allocated & group_to_mask(group)) != 0);
+}
+
+
+/**
+ * @brief Set group allocated indication.
+ *
+ * @param[in] group_num Specifies the group to set the "allocated" indication.
+ */
+__STATIC_INLINE void group_allocated_set(nrf_ppi_channel_group_t group)
+{
+ m_groups_allocated |= group_to_mask(group);
+}
+
+
+/**
+ * @brief Clear group allocated indication.
+ *
+ * @param[in] group_num Specifies the group to clear the "allocated" indication.
+ */
+__STATIC_INLINE void group_allocated_clr(nrf_ppi_channel_group_t group)
+{
+ m_groups_allocated &= ~group_to_mask(group);
+}
+
+
+/**
+ * @brief Clear all allocated groups.
+ */
+__STATIC_INLINE void group_allocated_clr_all()
+{
+ m_groups_allocated &= ~NRFX_PPI_ALL_APP_GROUPS_MASK;
+}
+
+
+void nrfx_ppi_free_all(void)
+{
+ uint32_t mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
+ nrf_ppi_channel_group_t group;
+
+ // Disable all channels and groups
+ nrf_ppi_channels_disable(NRFX_PPI_ALL_APP_CHANNELS_MASK);
+
+ for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
+ {
+ if (mask & group_to_mask(group))
+ {
+ nrf_ppi_channel_group_clear(group);
+ }
+ }
+ channel_allocated_clr_all();
+ group_allocated_clr_all();
+}
+
+
+nrfx_err_t nrfx_ppi_channel_alloc(nrf_ppi_channel_t * p_channel)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ nrf_ppi_channel_t channel;
+ uint32_t mask = 0;
+ err_code = NRFX_ERROR_NO_MEM;
+
+ mask = NRFX_PPI_PROG_APP_CHANNELS_MASK;
+ for (channel = NRF_PPI_CHANNEL0;
+ mask != 0;
+ mask &= ~nrfx_ppi_channel_to_mask(channel), channel++)
+ {
+ NRFX_CRITICAL_SECTION_ENTER();
+ if ((mask & nrfx_ppi_channel_to_mask(channel)) && (!is_allocated_channel(channel)))
+ {
+ channel_allocated_set(channel);
+ *p_channel = channel;
+ err_code = NRFX_SUCCESS;
+ }
+ NRFX_CRITICAL_SECTION_EXIT();
+ if (err_code == NRFX_SUCCESS)
+ {
+ NRFX_LOG_INFO("Allocated channel: %d.", channel);
+ break;
+ }
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_channel_free(nrf_ppi_channel_t channel)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_programmable_app_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ // First disable this channel
+ nrf_ppi_channel_disable(channel);
+ NRFX_CRITICAL_SECTION_ENTER();
+ channel_allocated_clr(channel);
+ NRFX_CRITICAL_SECTION_EXIT();
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep)
+{
+ if ((uint32_t *)eep == NULL || (uint32_t *)tep == NULL)
+ {
+ return NRFX_ERROR_NULL;
+ }
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_programmable_app_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (!is_allocated_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_channel_endpoint_setup(channel, eep, tep);
+ NRFX_LOG_INFO("Assigned channel: %d, event end point: %x, task end point: %x.",
+ channel,
+ eep,
+ tep);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+#ifdef PPI_FEATURE_FORKS_PRESENT
+ if (!is_programmable_app_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (!is_allocated_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_fork_endpoint_setup(channel, fork_tep);
+ NRFX_LOG_INFO("Fork assigned channel: %d, task end point: %d.", channel, fork_tep);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+#else
+ err_code = NRFX_ERROR_NOT_SUPPORTED;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+#endif
+}
+
+nrfx_err_t nrfx_ppi_channel_enable(nrf_ppi_channel_t channel)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_channel_enable(channel);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_channel_disable(nrf_ppi_channel_t channel)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_channel_disable(channel);
+ err_code = NRFX_SUCCESS;
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_group_alloc(nrf_ppi_channel_group_t * p_group)
+{
+ nrfx_err_t err_code;
+ uint32_t mask = 0;
+ nrf_ppi_channel_group_t group;
+
+ err_code = NRFX_ERROR_NO_MEM;
+
+ mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
+ for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
+ {
+ NRFX_CRITICAL_SECTION_ENTER();
+ if ((mask & group_to_mask(group)) && (!is_allocated_group(group)))
+ {
+ group_allocated_set(group);
+ *p_group = group;
+ err_code = NRFX_SUCCESS;
+ }
+ NRFX_CRITICAL_SECTION_EXIT();
+ if (err_code == NRFX_SUCCESS)
+ {
+ NRFX_LOG_INFO("Allocated group: %d.", group);
+ break;
+ }
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_group_free(nrf_ppi_channel_group_t group)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ if (!is_allocated_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_group_disable(group);
+ NRFX_CRITICAL_SECTION_ENTER();
+ group_allocated_clr(group);
+ NRFX_CRITICAL_SECTION_EXIT();
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_group_enable(nrf_ppi_channel_group_t group)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (!is_allocated_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else
+ {
+ nrf_ppi_group_enable(group);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_ppi_group_disable(nrf_ppi_channel_group_t group)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ nrf_ppi_group_disable(group);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_ppi_channels_remove_from_group(uint32_t channel_mask,
+ nrf_ppi_channel_group_t group)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (!is_allocated_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else if (!are_app_channels(channel_mask))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ NRFX_CRITICAL_SECTION_ENTER();
+ nrf_ppi_channels_remove_from_group(channel_mask, group);
+ NRFX_CRITICAL_SECTION_EXIT();
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_ppi_channels_include_in_group(uint32_t channel_mask,
+ nrf_ppi_channel_group_t group)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (!is_app_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else if (!is_allocated_group(group))
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else if (!are_app_channels(channel_mask))
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ NRFX_CRITICAL_SECTION_ENTER();
+ nrf_ppi_channels_include_in_group(channel_mask, group);
+ NRFX_CRITICAL_SECTION_EXIT();
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+#endif // NRFX_CHECK(NRFX_PPI_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pwm.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pwm.c
new file mode 100644
index 0000000..3a6581f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_pwm.c
@@ -0,0 +1,515 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_PWM_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_PWM0_ENABLED) || NRFX_CHECK(NRFX_PWM1_ENABLED) || \
+ NRFX_CHECK(NRFX_PWM2_ENABLED) || NRFX_CHECK(NRFX_PWM3_ENABLED))
+#error "No enabled PWM instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_pwm.h>
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE PWM
+#include <nrfx_log.h>
+
+#if NRFX_CHECK(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+// The workaround uses interrupts to wake up the CPU and ensure it is active
+// when PWM is about to start a DMA transfer. For initial transfer, done when
+// a playback is started via PPI, a specific EGU instance is used to generate
+// an interrupt. During the playback, the PWM interrupt triggered on SEQEND
+// event of a preceding sequence is used to protect the transfer done for
+// the next sequence to be played.
+#include <hal/nrf_egu.h>
+#define USE_DMA_ISSUE_WORKAROUND
+#endif
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+#define EGU_IRQn(i) EGU_IRQn_(i)
+#define EGU_IRQn_(i) SWI##i##_EGU##i##_IRQn
+#define EGU_IRQHandler(i) EGU_IRQHandler_(i)
+#define EGU_IRQHandler_(i) nrfx_swi_##i##_irq_handler
+#define DMA_ISSUE_EGU_IDX NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE
+#define DMA_ISSUE_EGU NRFX_CONCAT_2(NRF_EGU, DMA_ISSUE_EGU_IDX)
+#define DMA_ISSUE_EGU_IRQn EGU_IRQn(DMA_ISSUE_EGU_IDX)
+#define DMA_ISSUE_EGU_IRQHandler EGU_IRQHandler(DMA_ISSUE_EGU_IDX)
+#endif
+
+// Control block - driver instance local data.
+typedef struct
+{
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ uint32_t starting_task_address;
+#endif
+ nrfx_pwm_handler_t handler;
+ nrfx_drv_state_t volatile state;
+ uint8_t flags;
+} pwm_control_block_t;
+static pwm_control_block_t m_cb[NRFX_PWM_ENABLED_COUNT];
+
+static void configure_pins(nrfx_pwm_t const * const p_instance,
+ nrfx_pwm_config_t const * p_config)
+{
+ uint32_t out_pins[NRF_PWM_CHANNEL_COUNT];
+ uint8_t i;
+
+ for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i)
+ {
+ uint8_t output_pin = p_config->output_pins[i];
+ if (output_pin != NRFX_PWM_PIN_NOT_USED)
+ {
+ bool inverted = output_pin & NRFX_PWM_PIN_INVERTED;
+ out_pins[i] = output_pin & ~NRFX_PWM_PIN_INVERTED;
+
+ if (inverted)
+ {
+ nrf_gpio_pin_set(out_pins[i]);
+ }
+ else
+ {
+ nrf_gpio_pin_clear(out_pins[i]);
+ }
+
+ nrf_gpio_cfg_output(out_pins[i]);
+ }
+ else
+ {
+ out_pins[i] = NRF_PWM_PIN_NOT_CONNECTED;
+ }
+ }
+
+ nrf_pwm_pins_set(p_instance->p_registers, out_pins);
+}
+
+
+nrfx_err_t nrfx_pwm_init(nrfx_pwm_t const * const p_instance,
+ nrfx_pwm_config_t const * p_config,
+ nrfx_pwm_handler_t handler)
+{
+ NRFX_ASSERT(p_config);
+
+ nrfx_err_t err_code;
+
+ pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ p_cb->handler = handler;
+
+ configure_pins(p_instance, p_config);
+
+ nrf_pwm_enable(p_instance->p_registers);
+ nrf_pwm_configure(p_instance->p_registers,
+ p_config->base_clock, p_config->count_mode, p_config->top_value);
+ nrf_pwm_decoder_set(p_instance->p_registers,
+ p_config->load_mode, p_config->step_mode);
+
+ nrf_pwm_shorts_set(p_instance->p_registers, 0);
+ nrf_pwm_int_set(p_instance->p_registers, 0);
+ nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_LOOPSDONE);
+ nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND0);
+ nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND1);
+ nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
+
+ // The workaround for nRF52 Anomaly 109 "protects" DMA transfers by handling
+ // interrupts generated on SEQEND0 and SEQEND1 events (this ensures that
+ // the 64 MHz clock is ready when data for the next sequence to be played
+ // is read). Therefore, the PWM interrupt must be enabled even if the event
+ // handler is not used.
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ NRFX_IRQ_PRIORITY_SET(DMA_ISSUE_EGU_IRQn, p_config->irq_priority);
+ NRFX_IRQ_ENABLE(DMA_ISSUE_EGU_IRQn);
+#else
+ if (p_cb->handler)
+#endif
+ {
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_registers),
+ p_config->irq_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_registers));
+ }
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+void nrfx_pwm_uninit(nrfx_pwm_t const * const p_instance)
+{
+ pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_registers));
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ NRFX_IRQ_DISABLE(DMA_ISSUE_EGU_IRQn);
+#endif
+
+ nrf_pwm_disable(p_instance->p_registers);
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+
+static uint32_t start_playback(nrfx_pwm_t const * const p_instance,
+ pwm_control_block_t * p_cb,
+ uint8_t flags,
+ nrf_pwm_task_t starting_task)
+{
+ p_cb->state = NRFX_DRV_STATE_POWERED_ON;
+ p_cb->flags = flags;
+
+ if (p_cb->handler)
+ {
+ // The notification about finished playback is by default enabled,
+ // but this can be suppressed.
+ // The notification that the peripheral has stopped is always enabled.
+ uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK |
+ NRF_PWM_INT_STOPPED_MASK;
+
+ // The workaround for nRF52 Anomaly 109 "protects" DMA transfers by
+ // handling interrupts generated on SEQEND0 and SEQEND1 events (see
+ // 'nrfx_pwm_init'), hence these events must be always enabled
+ // to generate interrupts.
+ // However, the user handler is called for them only when requested
+ // (see 'irq_handler').
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ int_mask |= NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK;
+#else
+ if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ0)
+ {
+ int_mask |= NRF_PWM_INT_SEQEND0_MASK;
+ }
+ if (flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ1)
+ {
+ int_mask |= NRF_PWM_INT_SEQEND1_MASK;
+ }
+#endif
+ if (flags & NRFX_PWM_FLAG_NO_EVT_FINISHED)
+ {
+ int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK;
+ }
+
+ nrf_pwm_int_set(p_instance->p_registers, int_mask);
+ }
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ else
+ {
+ nrf_pwm_int_set(p_instance->p_registers,
+ NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK);
+ }
+#endif
+
+ nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
+
+ if (flags & NRFX_PWM_FLAG_START_VIA_TASK)
+ {
+ uint32_t starting_task_address =
+ nrf_pwm_task_address_get(p_instance->p_registers, starting_task);
+
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ // To "protect" the initial DMA transfer it is required to start
+ // the PWM by triggering the proper task from EGU interrupt handler,
+ // it is not safe to do it directly via PPI.
+ p_cb->starting_task_address = starting_task_address;
+ nrf_egu_int_enable(DMA_ISSUE_EGU,
+ nrf_egu_int_get(DMA_ISSUE_EGU, p_instance->drv_inst_idx));
+ return (uint32_t)nrf_egu_task_trigger_address_get(DMA_ISSUE_EGU,
+ p_instance->drv_inst_idx);
+#else
+ return starting_task_address;
+#endif
+ }
+
+ nrf_pwm_task_trigger(p_instance->p_registers, starting_task);
+ return 0;
+}
+
+
+uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_sequence_t const * p_sequence,
+ uint16_t playback_count,
+ uint32_t flags)
+{
+ pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(playback_count > 0);
+ NRFX_ASSERT(nrfx_is_in_ram(p_sequence->values.p_raw));
+
+ // To take advantage of the looping mechanism, we need to use both sequences
+ // (single sequence can be played back only once).
+ nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence);
+ nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence);
+ bool odd = (playback_count & 1);
+ nrf_pwm_loop_set(p_instance->p_registers,
+ (playback_count / 2) + (odd ? 1 : 0));
+
+ uint32_t shorts_mask;
+ if (flags & NRFX_PWM_FLAG_STOP)
+ {
+ shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
+ }
+ else if (flags & NRFX_PWM_FLAG_LOOP)
+ {
+ shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK
+ : NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ }
+ else
+ {
+ shorts_mask = 0;
+ }
+ nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
+
+ NRFX_LOG_INFO("Function: %s, sequence length: %d.",
+ __func__,
+ p_sequence->length);
+ NRFX_LOG_DEBUG("Sequence data:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence->values.p_raw,
+ p_sequence->length * sizeof(uint16_t));
+ return start_playback(p_instance, p_cb, flags,
+ odd ? NRF_PWM_TASK_SEQSTART1 : NRF_PWM_TASK_SEQSTART0);
+}
+
+
+uint32_t nrfx_pwm_complex_playback(nrfx_pwm_t const * const p_instance,
+ nrf_pwm_sequence_t const * p_sequence_0,
+ nrf_pwm_sequence_t const * p_sequence_1,
+ uint16_t playback_count,
+ uint32_t flags)
+{
+ pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(playback_count > 0);
+ NRFX_ASSERT(nrfx_is_in_ram(p_sequence_0->values.p_raw));
+ NRFX_ASSERT(nrfx_is_in_ram(p_sequence_1->values.p_raw));
+
+ nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence_0);
+ nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence_1);
+ nrf_pwm_loop_set(p_instance->p_registers, playback_count);
+
+ uint32_t shorts_mask;
+ if (flags & NRFX_PWM_FLAG_STOP)
+ {
+ shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
+ }
+ else if (flags & NRFX_PWM_FLAG_LOOP)
+ {
+ shorts_mask = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ }
+ else
+ {
+ shorts_mask = 0;
+ }
+ nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
+
+ NRFX_LOG_INFO("Function: %s, sequence 0 length: %d.",
+ __func__,
+ p_sequence_0->length);
+ NRFX_LOG_INFO("Function: %s, sequence 1 length: %d.",
+ __func__,
+ p_sequence_1->length);
+ NRFX_LOG_DEBUG("Sequence 0 data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_sequence_0->values.p_raw,
+ p_sequence_0->length * sizeof(uint16_t));
+ NRFX_LOG_DEBUG("Sequence 1 data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_sequence_1->values.p_raw,
+ p_sequence_1->length * sizeof(uint16_t));
+ return start_playback(p_instance, p_cb, flags, NRF_PWM_TASK_SEQSTART0);
+}
+
+
+bool nrfx_pwm_stop(nrfx_pwm_t const * const p_instance,
+ bool wait_until_stopped)
+{
+ NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ bool ret_val = false;
+
+ if (nrfx_pwm_is_stopped(p_instance))
+ {
+ ret_val = true;
+ }
+ else
+ {
+ nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP);
+
+ do {
+ if (nrfx_pwm_is_stopped(p_instance))
+ {
+ ret_val = true;
+ break;
+ }
+ } while (wait_until_stopped);
+ }
+
+ NRFX_LOG_INFO("%s returned %d.", __func__, ret_val);
+ return ret_val;
+}
+
+
+bool nrfx_pwm_is_stopped(nrfx_pwm_t const * const p_instance)
+{
+ pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ bool ret_val = false;
+
+ // If the event handler is used (interrupts are enabled), the state will
+ // be changed in interrupt handler when the STOPPED event occurs.
+ if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
+ {
+ ret_val = true;
+ }
+ // If interrupts are disabled, we must check the STOPPED event here.
+ if (nrf_pwm_event_check(p_instance->p_registers, NRF_PWM_EVENT_STOPPED))
+ {
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled.");
+ ret_val = true;
+ }
+
+ NRFX_LOG_INFO("%s returned %d.", __func__, ret_val);
+ return ret_val;
+}
+
+
+static void irq_handler(NRF_PWM_Type * p_pwm, pwm_control_block_t * p_cb)
+{
+ // The user handler is called for SEQEND0 and SEQEND1 events only when the
+ // user asks for it (by setting proper flags when starting the playback).
+ if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND0))
+ {
+ nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND0);
+ if ((p_cb->flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ0) && p_cb->handler)
+ {
+ p_cb->handler(NRFX_PWM_EVT_END_SEQ0);
+ }
+ }
+ if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND1))
+ {
+ nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND1);
+ if ((p_cb->flags & NRFX_PWM_FLAG_SIGNAL_END_SEQ1) && p_cb->handler)
+ {
+ p_cb->handler(NRFX_PWM_EVT_END_SEQ1);
+ }
+ }
+ // For LOOPSDONE the handler is called by default, but the user can disable
+ // this (via flags).
+ if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_LOOPSDONE))
+ {
+ nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_LOOPSDONE);
+ if (!(p_cb->flags & NRFX_PWM_FLAG_NO_EVT_FINISHED) && p_cb->handler)
+ {
+ p_cb->handler(NRFX_PWM_EVT_FINISHED);
+ }
+ }
+
+ // The STOPPED event is always propagated to the user handler.
+ if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_STOPPED))
+ {
+ nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_STOPPED);
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ if (p_cb->handler)
+ {
+ p_cb->handler(NRFX_PWM_EVT_STOPPED);
+ }
+ }
+}
+
+
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+// See 'start_playback' why this is needed.
+void DMA_ISSUE_EGU_IRQHandler(void)
+{
+ int i;
+ for (i = 0; i < NRFX_PWM_ENABLED_COUNT; ++i)
+ {
+ volatile uint32_t * p_event_reg =
+ nrf_egu_event_triggered_address_get(DMA_ISSUE_EGU, i);
+ if (*p_event_reg)
+ {
+ *p_event_reg = 0;
+ *(volatile uint32_t *)(m_cb[i].starting_task_address) = 1;
+ }
+ }
+}
+#endif
+
+
+#if NRFX_CHECK(NRFX_PWM0_ENABLED)
+void nrfx_pwm_0_irq_handler(void)
+{
+ irq_handler(NRF_PWM0, &m_cb[NRFX_PWM0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_PWM1_ENABLED)
+void nrfx_pwm_1_irq_handler(void)
+{
+ irq_handler(NRF_PWM1, &m_cb[NRFX_PWM1_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_PWM2_ENABLED)
+void nrfx_pwm_2_irq_handler(void)
+{
+ irq_handler(NRF_PWM2, &m_cb[NRFX_PWM2_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_PWM3_ENABLED)
+void nrfx_pwm_3_irq_handler(void)
+{
+ irq_handler(NRF_PWM3, &m_cb[NRFX_PWM3_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_PWM_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qdec.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qdec.c
new file mode 100644
index 0000000..c7994d1
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qdec.c
@@ -0,0 +1,201 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_QDEC_ENABLED)
+
+#include <nrfx_qdec.h>
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE QDEC
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_QDEC_EVENT_SAMPLERDY ? "NRF_QDEC_EVENT_SAMPLERDY" : \
+ (event == NRF_QDEC_EVENT_REPORTRDY ? "NRF_QDEC_EVENT_REPORTRDY" : \
+ (event == NRF_QDEC_EVENT_ACCOF ? "NRF_QDEC_EVENT_ACCOF" : \
+ "UNKNOWN EVENT")))
+
+
+static nrfx_qdec_event_handler_t m_qdec_event_handler = NULL;
+static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
+
+void nrfx_qdec_irq_handler(void)
+{
+ nrfx_qdec_event_t event;
+ if ( nrf_qdec_event_check(NRF_QDEC_EVENT_SAMPLERDY) &&
+ nrf_qdec_int_enable_check(NRF_QDEC_INT_SAMPLERDY_MASK) )
+ {
+ nrf_qdec_event_clear(NRF_QDEC_EVENT_SAMPLERDY);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_SAMPLERDY));
+
+ event.type = NRF_QDEC_EVENT_SAMPLERDY;
+ event.data.sample.value = (int8_t)nrf_qdec_sample_get();
+ m_qdec_event_handler(event);
+ }
+
+ if ( nrf_qdec_event_check(NRF_QDEC_EVENT_REPORTRDY) &&
+ nrf_qdec_int_enable_check(NRF_QDEC_INT_REPORTRDY_MASK) )
+ {
+ nrf_qdec_event_clear(NRF_QDEC_EVENT_REPORTRDY);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_REPORTRDY));
+
+ event.type = NRF_QDEC_EVENT_REPORTRDY;
+
+ event.data.report.acc = (int16_t)nrf_qdec_accread_get();
+ event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get();
+ m_qdec_event_handler(event);
+ }
+
+ if ( nrf_qdec_event_check(NRF_QDEC_EVENT_ACCOF) &&
+ nrf_qdec_int_enable_check(NRF_QDEC_INT_ACCOF_MASK) )
+ {
+ nrf_qdec_event_clear(NRF_QDEC_EVENT_ACCOF);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_QDEC_EVENT_ACCOF));
+
+ event.type = NRF_QDEC_EVENT_ACCOF;
+ m_qdec_event_handler(event);
+ }
+}
+
+
+nrfx_err_t nrfx_qdec_init(nrfx_qdec_config_t const * p_config,
+ nrfx_qdec_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ nrfx_err_t err_code;
+
+ if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_qdec_event_handler = event_handler;
+
+ nrf_qdec_sampleper_set(p_config->sampleper);
+ nrf_gpio_cfg_input(p_config->pselled, NRF_GPIO_PIN_NOPULL);
+ nrf_gpio_cfg_input(p_config->psela, NRF_GPIO_PIN_NOPULL);
+ nrf_gpio_cfg_input(p_config->pselb, NRF_GPIO_PIN_NOPULL);
+ nrf_qdec_pio_assign(p_config->psela, p_config->pselb, p_config->pselled);
+ nrf_qdec_ledpre_set(p_config->ledpre);
+ nrf_qdec_ledpol_set(p_config->ledpol);
+ nrf_qdec_shorts_enable(NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK);
+
+ if (p_config->dbfen)
+ {
+ nrf_qdec_dbfen_enable();
+ }
+ else
+ {
+ nrf_qdec_dbfen_disable();
+ }
+
+ uint32_t int_mask = NRF_QDEC_INT_ACCOF_MASK;
+
+ if (p_config->reportper != NRF_QDEC_REPORTPER_DISABLED)
+ {
+ nrf_qdec_reportper_set(p_config->reportper);
+ int_mask |= NRF_QDEC_INT_REPORTRDY_MASK;
+ }
+
+ if (p_config->sample_inten)
+ {
+ int_mask |= NRF_QDEC_INT_SAMPLERDY_MASK;
+ }
+
+ nrf_qdec_int_enable(int_mask);
+ NRFX_IRQ_PRIORITY_SET(QDEC_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(QDEC_IRQn);
+
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_qdec_uninit(void)
+{
+ NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrfx_qdec_disable();
+ NRFX_IRQ_DISABLE(QDEC_IRQn);
+ m_state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_qdec_enable(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_qdec_enable();
+ nrf_qdec_task_trigger(NRF_QDEC_TASK_START);
+ m_state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled.");
+}
+
+void nrfx_qdec_disable(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_qdec_task_trigger(NRF_QDEC_TASK_STOP);
+ nrf_qdec_disable();
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled.");
+}
+
+void nrfx_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_qdec_task_trigger(NRF_QDEC_TASK_READCLRACC);
+
+ *p_acc = (int16_t)nrf_qdec_accread_get();
+ *p_accdbl = (int16_t)nrf_qdec_accdblread_get();
+
+ NRFX_LOG_DEBUG("Accumulators data, ACC register:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_acc, sizeof(p_acc[0]));
+ NRFX_LOG_DEBUG("Accumulators data, ACCDBL register:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_accdbl, sizeof(p_accdbl[0]));
+}
+
+#endif // NRFX_CHECK(NRFX_QDEC_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qspi.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qspi.c
new file mode 100644
index 0000000..93ffeff
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_qspi.c
@@ -0,0 +1,337 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_QSPI_ENABLED)
+
+#include <nrfx_qspi.h>
+
+
+/**
+ * @brief Command byte used to read status register.
+ *
+ */
+#define QSPI_STD_CMD_RDSR 0x05
+
+/**
+ * @brief Byte used to mask status register and retrieve the write-in-progess bit.
+ *
+ */
+#define QSPI_MEM_STATUSREG_WIP_Pos 0x01
+
+/**
+ * @brief Default time used in timeout function.
+ */
+#define QSPI_DEF_WAIT_TIME_US 10
+
+/**
+ * @brief Default number of tries in timeout function.
+ */
+#define QSPI_DEF_WAIT_ATTEMPTS 100
+
+/**
+ * @brief Control block - driver instance local data.
+ */
+typedef struct
+{
+ nrfx_qspi_handler_t handler; /**< Handler. */
+ nrfx_drv_state_t state; /**< Driver state. */
+ volatile bool interrupt_driven; /**< Information if the current operation is performed and is interrupt-driven. */
+ void * p_context; /**< Driver context used in interrupt. */
+} qspi_control_block_t;
+
+static qspi_control_block_t m_cb;
+
+static nrfx_err_t qspi_task_perform(nrf_qspi_task_t task)
+{
+ // Wait for peripheral
+ if (m_cb.interrupt_driven)
+ {
+ return NRFX_ERROR_BUSY;
+ }
+
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+
+ if (m_cb.handler)
+ {
+ m_cb.interrupt_driven = true;
+ nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
+ }
+
+ nrf_qspi_task_trigger(NRF_QSPI, task);
+
+ if (m_cb.handler == NULL)
+ {
+ while (!nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY))
+ {};
+ }
+ return NRFX_SUCCESS;
+}
+
+static bool qspi_pins_configure(nrf_qspi_pins_t const * p_config)
+{
+ // Check if the user set meaningful values to struct fields. If not, return false.
+ if ((p_config->sck_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
+ (p_config->csn_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
+ (p_config->io0_pin == NRF_QSPI_PIN_NOT_CONNECTED) ||
+ (p_config->io1_pin == NRF_QSPI_PIN_NOT_CONNECTED))
+ {
+ return false;
+ }
+
+ nrf_qspi_pins_set(NRF_QSPI, p_config);
+
+ return true;
+}
+
+nrfx_err_t nrfx_qspi_init(nrfx_qspi_config_t const * p_config,
+ nrfx_qspi_handler_t handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ return NRFX_ERROR_INVALID_STATE;
+ }
+
+ if (!qspi_pins_configure(&p_config->pins))
+ {
+ return NRFX_ERROR_INVALID_PARAM;
+ }
+
+ nrf_qspi_xip_offset_set(NRF_QSPI, p_config->xip_offset);
+ nrf_qspi_ifconfig0_set(NRF_QSPI, &p_config->prot_if);
+ nrf_qspi_ifconfig1_set(NRF_QSPI, &p_config->phy_if);
+
+ m_cb.interrupt_driven = false;
+ m_cb.handler = handler;
+ m_cb.p_context = p_context;
+
+ /* QSPI interrupt is disabled because the device should be enabled in polling mode (wait for activate
+ task event ready)*/
+ nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
+
+ if (handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(QSPI_IRQn, p_config->irq_priority);
+ NRFX_IRQ_ENABLE(QSPI_IRQn);
+ }
+
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+
+ nrf_qspi_enable(NRF_QSPI);
+
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+ nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);
+
+ // Waiting for the peripheral to activate
+ bool result;
+ NRFX_WAIT_FOR(nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY),
+ QSPI_DEF_WAIT_ATTEMPTS,
+ QSPI_DEF_WAIT_TIME_US,
+ result);
+
+ if (!result)
+ {
+ return NRFX_ERROR_TIMEOUT;
+ }
+
+ return NRFX_SUCCESS;
+}
+
+nrfx_err_t nrfx_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config,
+ void const * p_tx_buffer,
+ void * p_rx_buffer)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ if (m_cb.interrupt_driven)
+ {
+ return NRFX_ERROR_BUSY;
+ }
+
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+ /* In some cases, only opcode should be sent. To prevent execution, set function code is
+ * surrounded by an if.
+ */
+ if (p_tx_buffer)
+ {
+ nrf_qspi_cinstrdata_set(NRF_QSPI, p_config->length, p_tx_buffer);
+ }
+ nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
+
+ nrf_qspi_cinstr_transfer_start(NRF_QSPI, p_config);
+
+ bool result;
+ NRFX_WAIT_FOR(nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY),
+ QSPI_DEF_WAIT_ATTEMPTS,
+ QSPI_DEF_WAIT_TIME_US,
+ result);
+
+ if (!result)
+ {
+ // This timeout should never occur when WIPWAIT is not active, since in this
+ // case the QSPI peripheral should send the command immediately, without any
+ // waiting for previous write to complete.
+ NRFX_ASSERT(p_config->wipwait);
+
+ return NRFX_ERROR_TIMEOUT;
+ }
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+ nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
+
+ if (p_rx_buffer)
+ {
+ nrf_qspi_cinstrdata_get(NRF_QSPI, p_config->length, p_rx_buffer);
+ }
+
+ return NRFX_SUCCESS;
+}
+
+nrfx_err_t nrfx_qspi_cinstr_quick_send(uint8_t opcode,
+ nrf_qspi_cinstr_len_t length,
+ void const * p_tx_buffer)
+{
+ nrf_qspi_cinstr_conf_t config = NRFX_QSPI_DEFAULT_CINSTR(opcode, length);
+ return nrfx_qspi_cinstr_xfer(&config, p_tx_buffer, NULL);
+}
+
+nrfx_err_t nrfx_qspi_mem_busy_check(void)
+{
+ nrfx_err_t ret_code;
+ uint8_t status_value = 0;
+
+ nrf_qspi_cinstr_conf_t const config =
+ NRFX_QSPI_DEFAULT_CINSTR(QSPI_STD_CMD_RDSR,
+ NRF_QSPI_CINSTR_LEN_2B);
+ ret_code = nrfx_qspi_cinstr_xfer(&config, &status_value, &status_value);
+
+ if (ret_code != NRFX_SUCCESS)
+ {
+ return ret_code;
+ }
+
+ if ((status_value & QSPI_MEM_STATUSREG_WIP_Pos) != 0x00)
+ {
+ return NRFX_ERROR_BUSY;
+ }
+
+ return NRFX_SUCCESS;
+}
+
+void nrfx_qspi_uninit(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
+
+ nrf_qspi_disable(NRF_QSPI);
+
+ nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_DEACTIVATE);
+
+ // Workaround for nRF52840 anomaly 122: Current consumption is too high.
+ *(volatile uint32_t *)0x40029054ul = 1ul;
+
+ NRFX_IRQ_DISABLE(QSPI_IRQn);
+
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+
+ m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+nrfx_err_t nrfx_qspi_write(void const * p_tx_buffer,
+ size_t tx_buffer_length,
+ uint32_t dst_address)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(p_tx_buffer != NULL);
+
+ if (!nrfx_is_in_ram(p_tx_buffer))
+ {
+ return NRFX_ERROR_INVALID_ADDR;
+ }
+
+ nrf_qspi_write_buffer_set(NRF_QSPI, p_tx_buffer, tx_buffer_length, dst_address);
+ return qspi_task_perform(NRF_QSPI_TASK_WRITESTART);
+
+}
+
+nrfx_err_t nrfx_qspi_read(void * p_rx_buffer,
+ size_t rx_buffer_length,
+ uint32_t src_address)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(p_rx_buffer != NULL);
+
+ if (!nrfx_is_in_ram(p_rx_buffer))
+ {
+ return NRFX_ERROR_INVALID_ADDR;
+ }
+
+ nrf_qspi_read_buffer_set(NRF_QSPI, p_rx_buffer, rx_buffer_length, src_address);
+ return qspi_task_perform(NRF_QSPI_TASK_READSTART);
+}
+
+nrfx_err_t nrfx_qspi_erase(nrf_qspi_erase_len_t length,
+ uint32_t start_address)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrf_qspi_erase_ptr_set(NRF_QSPI, start_address, length);
+ return qspi_task_perform(NRF_QSPI_TASK_ERASESTART);
+}
+
+nrfx_err_t nrfx_qspi_chip_erase(void)
+{
+ return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_ALL, 0);
+}
+
+void nrfx_qspi_irq_handler(void)
+{
+ // Catch Event ready interrupts
+ if (nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY))
+ {
+ m_cb.interrupt_driven = false;
+ nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
+ m_cb.handler(NRFX_QSPI_EVENT_DONE, m_cb.p_context);
+ }
+}
+
+#endif // NRFX_CHECK(NRFX_QSPI_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rng.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rng.c
new file mode 100644
index 0000000..a179f7c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rng.c
@@ -0,0 +1,122 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_RNG_ENABLED)
+
+#include <nrfx_rng.h>
+
+#define NRFX_LOG_MODULE RNG
+#include <nrfx_log.h>
+
+/**
+ * @brief Internal state of RNG driver.
+ */
+static nrfx_drv_state_t m_rng_state;
+
+/**
+ * @brief Pointer to handler calling from interrupt routine.
+ */
+static nrfx_rng_evt_handler_t m_rng_hndl;
+
+nrfx_err_t nrfx_rng_init(nrfx_rng_config_t const * p_config, nrfx_rng_evt_handler_t handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(handler);
+ if (m_rng_state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ return NRFX_ERROR_ALREADY_INITIALIZED;
+ }
+
+ m_rng_hndl = handler;
+
+ if (p_config->error_correction)
+ {
+ nrf_rng_error_correction_enable();
+ }
+ nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
+ NRFX_IRQ_PRIORITY_SET(RNG_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(RNG_IRQn);
+
+ m_rng_state = NRFX_DRV_STATE_INITIALIZED;
+
+ return NRFX_SUCCESS;
+}
+
+void nrfx_rng_start(void)
+{
+ NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
+ nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
+ nrf_rng_task_trigger(NRF_RNG_TASK_START);
+}
+
+void nrfx_rng_stop(void)
+{
+ NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
+ nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
+}
+
+void nrfx_rng_uninit(void)
+{
+ NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);
+
+ nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
+ nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
+ NRFX_IRQ_DISABLE(RNG_IRQn);
+
+ m_rng_state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_rng_irq_handler(void)
+{
+ nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
+
+ uint8_t rng_value = nrf_rng_random_value_get();
+
+ m_rng_hndl(rng_value);
+
+ NRFX_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY.");
+}
+
+#endif // NRFX_CHECK(NRFX_RNG_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rtc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rtc.c
new file mode 100644
index 0000000..95e8605
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_rtc.c
@@ -0,0 +1,348 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_RTC_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_RTC0_ENABLED) || NRFX_CHECK(NRFX_RTC1_ENABLED) || \
+ NRFX_CHECK(NRFX_RTC2_ENABLED))
+#error "No enabled RTC instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_rtc.h>
+
+#define NRFX_LOG_MODULE RTC
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \
+ (event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \
+ (event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \
+ (event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \
+ (event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \
+ (event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : \
+ "UNKNOWN EVENT"))))))
+
+
+/**@brief RTC driver instance control block structure. */
+typedef struct
+{
+ nrfx_drv_state_t state; /**< Instance state. */
+ bool reliable; /**< Reliable mode flag. */
+ uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */
+} nrfx_rtc_cb_t;
+
+// User callbacks local storage.
+static nrfx_rtc_handler_t m_handlers[NRFX_RTC_ENABLED_COUNT];
+static nrfx_rtc_cb_t m_cb[NRFX_RTC_ENABLED_COUNT];
+
+nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
+ nrfx_rtc_config_t const * p_config,
+ nrfx_rtc_handler_t handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(handler);
+ nrfx_err_t err_code;
+
+ m_handlers[p_instance->instance_id] = handler;
+
+ if (m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ NRFX_IRQ_PRIORITY_SET(p_instance->irq, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(p_instance->irq);
+ nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler);
+ m_cb[p_instance->instance_id].reliable = p_config->reliable;
+ m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency;
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance)
+{
+ uint32_t mask = NRF_RTC_INT_TICK_MASK |
+ NRF_RTC_INT_OVERFLOW_MASK |
+ NRF_RTC_INT_COMPARE0_MASK |
+ NRF_RTC_INT_COMPARE1_MASK |
+ NRF_RTC_INT_COMPARE2_MASK |
+ NRF_RTC_INT_COMPARE3_MASK;
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ NRFX_IRQ_DISABLE(p_instance->irq);
+
+ nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
+ nrf_rtc_event_disable(p_instance->p_reg, mask);
+ nrf_rtc_int_disable(p_instance->p_reg, mask);
+
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
+
+ nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START);
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled.");
+}
+
+void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled.");
+}
+
+nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(channel<p_instance->cc_channel_count);
+
+ nrfx_err_t err_code;
+ uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
+ nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
+
+ nrf_rtc_event_disable(p_instance->p_reg,int_mask);
+ if (nrf_rtc_int_is_enabled(p_instance->p_reg,int_mask))
+ {
+ nrf_rtc_int_disable(p_instance->p_reg,int_mask);
+ if (nrf_rtc_event_pending(p_instance->p_reg,event))
+ {
+ nrf_rtc_event_clear(p_instance->p_reg,event);
+ err_code = NRFX_ERROR_TIMEOUT;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ }
+ NRFX_LOG_INFO("RTC id: %d, channel disabled: %lu.", p_instance->instance_id, channel);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
+ uint32_t channel,
+ uint32_t val,
+ bool enable_irq)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(channel<p_instance->cc_channel_count);
+
+ nrfx_err_t err_code;
+ uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
+ nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
+
+ nrf_rtc_event_disable(p_instance->p_reg, int_mask);
+ nrf_rtc_int_disable(p_instance->p_reg, int_mask);
+
+ val = RTC_WRAP(val);
+ if (m_cb[p_instance->instance_id].reliable)
+ {
+ nrf_rtc_cc_set(p_instance->p_reg,channel,val);
+ uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg);
+ int32_t diff = cnt - val;
+ if (cnt < val)
+ {
+ diff += RTC_COUNTER_COUNTER_Msk;
+ }
+ if (diff < m_cb[p_instance->instance_id].tick_latency)
+ {
+ err_code = NRFX_ERROR_TIMEOUT;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ }
+ else
+ {
+ nrf_rtc_cc_set(p_instance->p_reg,channel,val);
+ }
+
+ if (enable_irq)
+ {
+ nrf_rtc_event_clear(p_instance->p_reg,event);
+ nrf_rtc_int_enable(p_instance->p_reg, int_mask);
+ }
+ nrf_rtc_event_enable(p_instance->p_reg,int_mask);
+
+ NRFX_LOG_INFO("RTC id: %d, channel enabled: %lu, compare value: %lu.",
+ p_instance->instance_id,
+ channel,
+ val);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
+{
+ nrf_rtc_event_t event = NRF_RTC_EVENT_TICK;
+ uint32_t mask = NRF_RTC_INT_TICK_MASK;
+
+ nrf_rtc_event_clear(p_instance->p_reg, event);
+ nrf_rtc_event_enable(p_instance->p_reg, mask);
+ if (enable_irq)
+ {
+ nrf_rtc_int_enable(p_instance->p_reg, mask);
+ }
+ NRFX_LOG_INFO("Tick events enabled.");
+}
+
+void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance)
+{
+ uint32_t mask = NRF_RTC_INT_TICK_MASK;
+
+ nrf_rtc_event_disable(p_instance->p_reg, mask);
+ nrf_rtc_int_disable(p_instance->p_reg, mask);
+ NRFX_LOG_INFO("Tick events disabled.");
+}
+
+void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
+{
+ nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW;
+ uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
+
+ nrf_rtc_event_clear(p_instance->p_reg, event);
+ nrf_rtc_event_enable(p_instance->p_reg, mask);
+ if (enable_irq)
+ {
+ nrf_rtc_int_enable(p_instance->p_reg, mask);
+ }
+}
+
+void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance)
+{
+ uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
+ nrf_rtc_event_disable(p_instance->p_reg, mask);
+ nrf_rtc_int_disable(p_instance->p_reg, mask);
+}
+
+uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance)
+{
+ uint32_t ticks;
+ if (m_cb[p_instance->instance_id].reliable)
+ {
+ ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency;
+ }
+ else
+ {
+ ticks = RTC_COUNTER_COUNTER_Msk;
+ }
+ return ticks;
+}
+
+static void irq_handler(NRF_RTC_Type * p_reg,
+ uint32_t instance_id,
+ uint32_t channel_count)
+{
+ uint32_t i;
+ uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
+ nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;
+
+ for (i = 0; i < channel_count; i++)
+ {
+ if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event))
+ {
+ nrf_rtc_event_disable(p_reg,int_mask);
+ nrf_rtc_int_disable(p_reg,int_mask);
+ nrf_rtc_event_clear(p_reg,event);
+ NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
+ m_handlers[instance_id]((nrfx_rtc_int_type_t)i);
+ }
+ int_mask <<= 1;
+ event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
+ }
+ event = NRF_RTC_EVENT_TICK;
+ if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) &&
+ nrf_rtc_event_pending(p_reg, event))
+ {
+ nrf_rtc_event_clear(p_reg, event);
+ NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
+ m_handlers[instance_id](NRFX_RTC_INT_TICK);
+ }
+
+ event = NRF_RTC_EVENT_OVERFLOW;
+ if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) &&
+ nrf_rtc_event_pending(p_reg, event))
+ {
+ nrf_rtc_event_clear(p_reg,event);
+ NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
+ m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW);
+ }
+}
+
+#if NRFX_CHECK(NRFX_RTC0_ENABLED)
+void nrfx_rtc_0_irq_handler(void)
+{
+ irq_handler(NRF_RTC0, NRFX_RTC0_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(0));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_RTC1_ENABLED)
+void nrfx_rtc_1_irq_handler(void)
+{
+ irq_handler(NRF_RTC1, NRFX_RTC1_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(1));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_RTC2_ENABLED)
+void nrfx_rtc_2_irq_handler(void)
+{
+ irq_handler(NRF_RTC2, NRFX_RTC2_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(2));
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_RTC_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c
new file mode 100644
index 0000000..4ab3409
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c
@@ -0,0 +1,639 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SAADC_ENABLED)
+#include <nrfx_saadc.h>
+
+#define NRFX_LOG_MODULE SAADC
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \
+ (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \
+ (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \
+ (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \
+ (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \
+ (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : \
+ "UNKNOWN EVENT"))))))
+
+
+typedef enum
+{
+ NRF_SAADC_STATE_IDLE = 0,
+ NRF_SAADC_STATE_BUSY = 1,
+ NRF_SAADC_STATE_CALIBRATION = 2
+} nrf_saadc_state_t;
+
+
+typedef struct
+{
+ nrf_saadc_input_t pselp;
+ nrf_saadc_input_t pseln;
+} nrf_saadc_psel_buffer;
+
+/** @brief SAADC control block.*/
+typedef struct
+{
+ nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer.
+ volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer.
+ volatile uint16_t buffer_size; ///< Size of the sample buffer.
+ volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer.
+ volatile nrf_saadc_state_t adc_state; ///< State of the SAADC.
+ uint32_t limits_enabled_flags; ///< Enabled limits flags.
+ uint16_t secondary_buffer_size; ///< Size of the secondary buffer.
+ uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer.
+ nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels.
+ nrfx_drv_state_t state; ///< Driver initialization state.
+ uint8_t active_channels; ///< Number of enabled SAADC channels.
+ bool low_power_mode; ///< Indicates if low power mode is active.
+ bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer.
+} nrfx_saadc_cb_t;
+
+static nrfx_saadc_cb_t m_cb;
+
+#define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1))
+#define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel))
+#define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \
+ 4 * idx))
+#define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \
+ (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8)
+#define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \
+ ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH)
+#define HW_TIMEOUT 10000
+
+void nrfx_saadc_irq_handler(void)
+{
+ if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
+ {
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END));
+
+ if (!m_cb.low_power_mode || m_cb.conversions_end)
+ {
+ nrfx_saadc_evt_t evt;
+ evt.type = NRFX_SAADC_EVT_DONE;
+ evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
+ evt.data.done.size = m_cb.buffer_size;
+
+ if (m_cb.p_secondary_buffer == NULL)
+ {
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+ }
+ else
+ {
+ m_cb.buffer_size_left = m_cb.secondary_buffer_size;
+ m_cb.p_buffer = m_cb.p_secondary_buffer;
+ m_cb.buffer_size = m_cb.secondary_buffer_size;
+ m_cb.p_secondary_buffer = NULL;
+ if (!m_cb.low_power_mode)
+ {
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
+ }
+ }
+ m_cb.event_handler(&evt);
+ m_cb.conversions_end = false;
+ }
+ }
+ if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
+ {
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED));
+
+ if (m_cb.buffer_size_left > m_cb.active_channels)
+ {
+ // More samples to convert than for single event.
+ m_cb.buffer_size_left -= m_cb.active_channels;
+ nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size -
+ m_cb.buffer_size_left],
+ m_cb.active_channels);
+ }
+ else if ((m_cb.buffer_size_left == m_cb.active_channels) &&
+
+ (m_cb.p_secondary_buffer != NULL))
+ {
+ // Samples to convert for one event, prepare next buffer.
+ m_cb.conversions_end = true;
+ m_cb.buffer_size_left = 0;
+ nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer,
+ m_cb.active_channels);
+ }
+ else if (m_cb.buffer_size_left == m_cb.active_channels)
+ {
+ // Samples to convert for one event, but no second buffer.
+ m_cb.conversions_end = true;
+ m_cb.buffer_size_left = 0;
+ }
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
+ }
+ if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
+ {
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE));
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+
+ nrfx_saadc_evt_t evt;
+ evt.type = NRFX_SAADC_EVT_CALIBRATEDONE;
+ m_cb.event_handler(&evt);
+ }
+ if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
+ {
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+ }
+ else
+ {
+ uint32_t limit_flags = m_cb.limits_enabled_flags;
+ uint32_t flag_idx;
+ nrf_saadc_event_t event;
+
+ while (limit_flags)
+ {
+ flag_idx = __CLZ(limit_flags);
+ limit_flags &= ~((1UL << 31) >> flag_idx);
+ event = FLAG_IDX_TO_EVENT(flag_idx);
+ if (nrf_saadc_event_check(event))
+ {
+ nrf_saadc_event_clear(event);
+ nrfx_saadc_evt_t evt;
+ evt.type = NRFX_SAADC_EVT_LIMIT;
+ evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event);
+ evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event);
+ NRFX_LOG_DEBUG("Event limit, channel: %d, limit type: %d.",
+ evt.data.limit.channel,
+ evt.data.limit.limit_type);
+ m_cb.event_handler(&evt);
+ }
+ }
+ }
+}
+
+
+nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
+ nrfx_saadc_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ nrfx_err_t err_code;
+
+ if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_cb.event_handler = event_handler;
+ nrf_saadc_resolution_set(p_config->resolution);
+ nrf_saadc_oversample_set(p_config->oversample);
+ m_cb.low_power_mode = p_config->low_power_mode;
+ m_cb.state = NRFX_DRV_STATE_INITIALIZED;
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+ m_cb.active_channels = 0;
+ m_cb.limits_enabled_flags = 0;
+ m_cb.conversions_end = false;
+
+ nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
+ NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(SAADC_IRQn);
+ nrf_saadc_int_enable(NRF_SAADC_INT_END);
+
+ if (m_cb.low_power_mode)
+ {
+ nrf_saadc_int_enable(NRF_SAADC_INT_STARTED);
+ }
+
+ nrf_saadc_enable();
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+
+ return err_code;
+}
+
+
+void nrfx_saadc_uninit(void)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
+ NRFX_IRQ_DISABLE(SAADC_IRQn);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
+
+ // Wait for ADC being stopped.
+ bool result;
+ NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result);
+ NRFX_ASSERT(result);
+
+ nrf_saadc_disable();
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+
+ for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel)
+ {
+ if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
+ {
+ nrfx_err_t err_code = nrfx_saadc_channel_uninit(channel);
+ NRFX_ASSERT(err_code == NRFX_SUCCESS);
+ }
+ }
+
+ m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+
+nrfx_err_t nrfx_saadc_channel_init(uint8_t channel,
+ nrf_saadc_channel_config_t const * const p_config)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
+ // Oversampling can be used only with one channel.
+ NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) ||
+ (m_cb.active_channels == 0));
+ NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) &&
+ (p_config->pin_p > NRF_SAADC_INPUT_DISABLED));
+ NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD);
+
+ nrfx_err_t err_code;
+
+ // A channel can only be initialized if the driver is in the idle state.
+ if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#ifdef NRF52_PAN_74
+ if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
+ (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
+ {
+ nrf_saadc_disable();
+ }
+#endif //NRF52_PAN_74
+
+ if (m_cb.psel[channel].pselp == NRF_SAADC_INPUT_DISABLED)
+ {
+ ++m_cb.active_channels;
+ }
+ m_cb.psel[channel].pselp = p_config->pin_p;
+ m_cb.psel[channel].pseln = p_config->pin_n;
+ nrf_saadc_channel_init(channel, p_config);
+ nrf_saadc_channel_input_set(channel, p_config->pin_p, p_config->pin_n);
+
+#ifdef NRF52_PAN_74
+ if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
+ (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
+ {
+ nrf_saadc_enable();
+ }
+#endif //NRF52_PAN_74
+
+ NRFX_LOG_INFO("Channel initialized: %d.", channel);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel)
+{
+ NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrfx_err_t err_code;
+
+ // A channel can only be uninitialized if the driver is in the idle state.
+ if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
+ {
+ --m_cb.active_channels;
+ }
+ m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED;
+ m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED;
+ nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
+ nrfx_saadc_limits_set(channel, NRFX_SAADC_LIMITL_DISABLED, NRFX_SAADC_LIMITH_DISABLED);
+ NRFX_LOG_INFO("Channel denitialized: %d.", channel);
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+uint32_t nrfx_saadc_sample_task_get(void)
+{
+ return nrf_saadc_task_address_get(
+ m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE);
+}
+
+
+nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value)
+{
+ nrfx_err_t err_code;
+
+ if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ m_cb.adc_state = NRF_SAADC_STATE_BUSY;
+ nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
+ nrf_saadc_buffer_init(p_value, 1);
+ if (m_cb.active_channels > 1)
+ {
+ for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
+ {
+ nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
+ }
+ }
+ nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
+
+ bool result;
+ NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result);
+ NRFX_ASSERT(result);
+
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
+
+ NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel);
+
+ if (m_cb.active_channels > 1)
+ {
+ for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
+ {
+ nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln);
+ }
+ }
+
+ if (m_cb.low_power_mode)
+ {
+ nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
+ }
+ else
+ {
+ nrf_saadc_int_enable(NRF_SAADC_INT_END);
+ }
+
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT((size % m_cb.active_channels) == 0);
+ nrfx_err_t err_code;
+
+ nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
+ if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
+ {
+ nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
+ {
+ if ( m_cb.p_secondary_buffer)
+ {
+ nrf_saadc_int_enable(NRF_SAADC_INT_END);
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ m_cb.p_secondary_buffer = p_buffer;
+ m_cb.secondary_buffer_size = size;
+ if (!m_cb.low_power_mode)
+ {
+ while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
+ nrf_saadc_buffer_init(p_buffer, size);
+ }
+ nrf_saadc_int_enable(NRF_SAADC_INT_END);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ }
+ nrf_saadc_int_enable(NRF_SAADC_INT_END);
+ m_cb.adc_state = NRF_SAADC_STATE_BUSY;
+
+ m_cb.p_buffer = p_buffer;
+ m_cb.buffer_size = size;
+ m_cb.p_secondary_buffer = NULL;
+
+ NRFX_LOG_INFO("Function: %s, buffer length: %d, active channels: %d.",
+ __func__,
+ size,
+ m_cb.active_channels);
+
+ if (m_cb.low_power_mode)
+ {
+ m_cb.buffer_size_left = size;
+ nrf_saadc_buffer_init(p_buffer, m_cb.active_channels);
+ }
+ else
+ {
+ nrf_saadc_buffer_init(p_buffer, size);
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
+ }
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_saadc_sample()
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ if (m_cb.adc_state != NRF_SAADC_STATE_BUSY)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ }
+ else if (m_cb.low_power_mode)
+ {
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
+ }
+ else
+ {
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_saadc_calibrate_offset()
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrfx_err_t err_code;
+
+ if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION;
+
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
+ nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+bool nrfx_saadc_is_busy(void)
+{
+ return (m_cb.adc_state != NRF_SAADC_STATE_IDLE);
+}
+
+
+void nrfx_saadc_abort(void)
+{
+ if (nrfx_saadc_is_busy())
+ {
+ nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
+ nrf_saadc_int_enable(NRF_SAADC_INT_STOPPED);
+ nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
+
+ if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
+ {
+ m_cb.adc_state = NRF_SAADC_STATE_IDLE;
+ }
+ else
+ {
+ // Wait for ADC being stopped.
+ bool result;
+ NRFX_WAIT_FOR((m_cb.adc_state != NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result);
+ NRFX_ASSERT(result);
+ }
+
+ nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED);
+
+ m_cb.p_buffer = 0;
+ m_cb.p_secondary_buffer = 0;
+ NRFX_LOG_INFO("Conversion aborted.");
+ }
+}
+
+
+void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
+{
+ NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(m_cb.event_handler); // only non blocking mode supported
+ NRFX_ASSERT(limit_low >= NRFX_SAADC_LIMITL_DISABLED);
+ NRFX_ASSERT(limit_high <= NRFX_SAADC_LIMITH_DISABLED);
+ NRFX_ASSERT(limit_low < limit_high);
+ nrf_saadc_channel_limits_set(channel, limit_low, limit_high);
+
+ uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
+ if (limit_low == NRFX_SAADC_LIMITL_DISABLED)
+ {
+ m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
+ nrf_saadc_int_disable(int_mask);
+ }
+ else
+ {
+ m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
+ nrf_saadc_int_enable(int_mask);
+ }
+
+ int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
+ if (limit_high == NRFX_SAADC_LIMITH_DISABLED)
+ {
+ m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
+ nrf_saadc_int_disable(int_mask);
+ }
+ else
+ {
+ m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
+ nrf_saadc_int_enable(int_mask);
+ }
+}
+#endif // NRFX_CHECK(NRFX_SAADC_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spi.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spi.c
new file mode 100644
index 0000000..2c6bb44
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spi.c
@@ -0,0 +1,441 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SPI_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_SPI0_ENABLED) || NRFX_CHECK(NRFX_SPI1_ENABLED) || \
+ NRFX_CHECK(NRFX_SPI2_ENABLED))
+#error "No enabled SPI instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_spi.h>
+#include "prs/nrfx_prs.h"
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE SPI
+#include <nrfx_log.h>
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_spi_evt_handler_t handler;
+ void * p_context;
+ nrfx_spi_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy.
+ nrfx_drv_state_t state;
+ volatile bool transfer_in_progress;
+
+ // [no need for 'volatile' attribute for the following members, as they
+ // are not concurrently used in IRQ handlers and main line code]
+ uint8_t ss_pin;
+ uint8_t miso_pin;
+ uint8_t orc;
+ size_t bytes_transferred;
+
+ bool abort;
+} spi_control_block_t;
+static spi_control_block_t m_cb[NRFX_SPI_ENABLED_COUNT];
+
+
+nrfx_err_t nrfx_spi_init(nrfx_spi_t const * const p_instance,
+ nrfx_spi_config_t const * p_config,
+ nrfx_spi_evt_handler_t handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_SPI_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_SPI0_ENABLED)
+ nrfx_spi_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPI1_ENABLED)
+ nrfx_spi_1_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPI2_ENABLED)
+ nrfx_spi_2_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_reg,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ p_cb->handler = handler;
+ p_cb->p_context = p_context;
+
+ uint32_t mosi_pin;
+ uint32_t miso_pin;
+ // Configure pins used by the peripheral:
+ // - SCK - output with initial value corresponding with the SPI mode used:
+ // 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1);
+ // according to the reference manual guidelines this pin and its input
+ // buffer must always be connected for the SPI to work.
+ if (p_config->mode <= NRF_SPI_MODE_1)
+ {
+ nrf_gpio_pin_clear(p_config->sck_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_set(p_config->sck_pin);
+ }
+ nrf_gpio_cfg(p_config->sck_pin,
+ NRF_GPIO_PIN_DIR_OUTPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+ // - MOSI (optional) - output with initial value 0,
+ if (p_config->mosi_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ mosi_pin = p_config->mosi_pin;
+ nrf_gpio_pin_clear(mosi_pin);
+ nrf_gpio_cfg_output(mosi_pin);
+ }
+ else
+ {
+ mosi_pin = NRF_SPI_PIN_NOT_CONNECTED;
+ }
+ // - MISO (optional) - input,
+ if (p_config->miso_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ miso_pin = p_config->miso_pin;
+ nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRFX_SPI_MISO_PULL_CFG);
+ }
+ else
+ {
+ miso_pin = NRF_SPI_PIN_NOT_CONNECTED;
+ }
+ m_cb[p_instance->drv_inst_idx].miso_pin = p_config->miso_pin;
+ // - Slave Select (optional) - output with initial value 1 (inactive).
+ if (p_config->ss_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ nrf_gpio_pin_set(p_config->ss_pin);
+ nrf_gpio_cfg_output(p_config->ss_pin);
+ }
+ m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin;
+
+ NRF_SPI_Type * p_spi = p_instance->p_reg;
+ nrf_spi_pins_set(p_spi, p_config->sck_pin, mosi_pin, miso_pin);
+ nrf_spi_frequency_set(p_spi, p_config->frequency);
+ nrf_spi_configure(p_spi, p_config->mode, p_config->bit_order);
+
+ m_cb[p_instance->drv_inst_idx].orc = p_config->orc;
+
+ if (p_cb->handler)
+ {
+ nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
+ }
+
+ nrf_spi_enable(p_spi);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
+ p_config->irq_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
+ }
+
+ p_cb->transfer_in_progress = false;
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_spi_uninit(nrfx_spi_t const * const p_instance)
+{
+ spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
+ }
+
+ NRF_SPI_Type * p_spi = p_instance->p_reg;
+ if (p_cb->handler)
+ {
+ nrf_spi_int_disable(p_spi, NRF_SPI_ALL_INTS_MASK);
+ }
+
+ if (p_cb->miso_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ nrf_gpio_cfg_default(p_cb->miso_pin);
+ }
+ nrf_spi_disable(p_spi);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_reg);
+#endif
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+static void finish_transfer(spi_control_block_t * p_cb)
+{
+ // If Slave Select signal is used, this is the time to deactivate it.
+ if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ nrf_gpio_pin_set(p_cb->ss_pin);
+ }
+
+ // By clearing this flag before calling the handler we allow subsequent
+ // transfers to be started directly from the handler function.
+ p_cb->transfer_in_progress = false;
+
+ p_cb->evt.type = NRFX_SPI_EVENT_DONE;
+ p_cb->handler(&p_cb->evt, p_cb->p_context);
+}
+
+// This function is called from the IRQ handler or, in blocking mode, directly
+// from the 'spi_xfer' function.
+// It returns true as long as the transfer should be continued, otherwise (when
+// there is nothing more to send/receive) it returns false.
+static bool transfer_byte(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb)
+{
+ // Read the data byte received in this transfer (always, because no further
+ // READY event can be generated until the current byte is read out from the
+ // RXD register), and store it in the RX buffer (only when needed).
+ volatile uint8_t rx_data = nrf_spi_rxd_get(p_spi);
+ if (p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length)
+ {
+ p_cb->evt.xfer_desc.p_rx_buffer[p_cb->bytes_transferred] = rx_data;
+ }
+
+ ++p_cb->bytes_transferred;
+
+ // Check if there are more bytes to send or receive and write proper data
+ // byte (next one from TX buffer or over-run character) to the TXD register
+ // when needed.
+ // NOTE - we've already used 'p_cb->bytes_transferred + 1' bytes from our
+ // buffers, because we take advantage of double buffering of TXD
+ // register (so in effect one byte is still being transmitted now);
+ // see how the transfer is started in the 'spi_xfer' function.
+ size_t bytes_used = p_cb->bytes_transferred + 1;
+
+ if (p_cb->abort)
+ {
+ if (bytes_used < p_cb->evt.xfer_desc.tx_length)
+ {
+ p_cb->evt.xfer_desc.tx_length = bytes_used;
+ }
+ if (bytes_used < p_cb->evt.xfer_desc.rx_length)
+ {
+ p_cb->evt.xfer_desc.rx_length = bytes_used;
+ }
+ }
+
+ if (bytes_used < p_cb->evt.xfer_desc.tx_length)
+ {
+ nrf_spi_txd_set(p_spi, p_cb->evt.xfer_desc.p_tx_buffer[bytes_used]);
+ return true;
+ }
+ else if (bytes_used < p_cb->evt.xfer_desc.rx_length)
+ {
+ nrf_spi_txd_set(p_spi, p_cb->orc);
+ return true;
+ }
+
+ return (p_cb->bytes_transferred < p_cb->evt.xfer_desc.tx_length ||
+ p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length);
+}
+
+static void spi_xfer(NRF_SPI_Type * p_spi,
+ spi_control_block_t * p_cb,
+ nrfx_spi_xfer_desc_t const * p_xfer_desc)
+{
+ p_cb->bytes_transferred = 0;
+ nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
+
+ nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+
+ // Start the transfer by writing some byte to the TXD register;
+ // if TX buffer is not empty, take the first byte from this buffer,
+ // otherwise - use over-run character.
+ nrf_spi_txd_set(p_spi,
+ (p_xfer_desc->tx_length > 0 ? p_xfer_desc->p_tx_buffer[0] : p_cb->orc));
+
+ // TXD register is double buffered, so next byte to be transmitted can
+ // be written immediately, if needed, i.e. if TX or RX transfer is to
+ // be more that 1 byte long. Again - if there is something more in TX
+ // buffer send it, otherwise use over-run character.
+ if (p_xfer_desc->tx_length > 1)
+ {
+ nrf_spi_txd_set(p_spi, p_xfer_desc->p_tx_buffer[1]);
+ }
+ else if (p_xfer_desc->rx_length > 1)
+ {
+ nrf_spi_txd_set(p_spi, p_cb->orc);
+ }
+
+ // For blocking mode (user handler not provided) wait here for READY
+ // events (indicating that the byte from TXD register was transmitted
+ // and a new incoming byte was moved to the RXD register) and continue
+ // transaction until all requested bytes are transferred.
+ // In non-blocking mode - IRQ service routine will do this stuff.
+ if (p_cb->handler)
+ {
+ nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
+ }
+ else
+ {
+ do {
+ while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
+ nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+ NRFX_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY.");
+ } while (transfer_byte(p_spi, p_cb));
+ if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ nrf_gpio_pin_set(p_cb->ss_pin);
+ }
+ }
+}
+
+nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * const p_instance,
+ nrfx_spi_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+ spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
+ NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (p_cb->transfer_in_progress)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ if (p_cb->handler)
+ {
+ p_cb->transfer_in_progress = true;
+ }
+ }
+
+ p_cb->evt.xfer_desc = *p_xfer_desc;
+ p_cb->abort = false;
+
+ if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED)
+ {
+ nrf_gpio_pin_clear(p_cb->ss_pin);
+ }
+ if (flags)
+ {
+ p_cb->transfer_in_progress = false;
+ err_code = NRFX_ERROR_NOT_SUPPORTED;
+ }
+ else
+ {
+ spi_xfer(p_instance->p_reg, p_cb, p_xfer_desc);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_spi_abort(nrfx_spi_t const * p_instance)
+{
+ spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+ p_cb->abort = true;
+}
+
+static void irq_handler(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb)
+{
+ NRFX_ASSERT(p_cb->handler);
+
+ nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+ NRFX_LOG_DEBUG("Event: NRF_SPI_EVENT_READY.");
+
+ if (!transfer_byte(p_spi, p_cb))
+ {
+ finish_transfer(p_cb);
+ }
+}
+
+#if NRFX_CHECK(NRFX_SPI0_ENABLED)
+void nrfx_spi_0_irq_handler(void)
+{
+ irq_handler(NRF_SPI0, &m_cb[NRFX_SPI0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPI1_ENABLED)
+void nrfx_spi_1_irq_handler(void)
+{
+ irq_handler(NRF_SPI1, &m_cb[NRFX_SPI1_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPI2_ENABLED)
+void nrfx_spi_2_irq_handler(void)
+{
+ irq_handler(NRF_SPI2, &m_cb[NRFX_SPI2_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_SPI_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spim.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spim.c
new file mode 100644
index 0000000..cf16e26
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spim.c
@@ -0,0 +1,688 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SPIM_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_SPIM0_ENABLED) || NRFX_CHECK(NRFX_SPIM1_ENABLED) || \
+ NRFX_CHECK(NRFX_SPIM2_ENABLED) || NRFX_CHECK(NRFX_SPIM3_ENABLED))
+#error "No enabled SPIM instances. Check <nrfx_config.h>."
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) && !NRFX_CHECK(NRFX_SPIM3_ENABLED)
+#error "Extended options are available only in SPIM3 on the nRF52840 SoC."
+#endif
+
+#include <nrfx_spim.h>
+#include "prs/nrfx_prs.h"
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE SPIM
+#include <nrfx_log.h>
+
+#define SPIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
+ (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+ NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
+
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+#define SPIM0_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM0, __VA_ARGS__)
+#else
+#define SPIM0_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+#define SPIM1_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM1, __VA_ARGS__)
+#else
+#define SPIM1_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+#define SPIM2_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM2, __VA_ARGS__)
+#else
+#define SPIM2_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+#define SPIM3_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM3, __VA_ARGS__)
+#else
+#define SPIM3_LENGTH_VALIDATE(...) 0
+#endif
+
+#define SPIM_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) \
+ (SPIM0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+ SPIM1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+ SPIM2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+ SPIM3_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
+
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_spim_evt_handler_t handler;
+ void * p_context;
+ nrfx_spim_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy.
+ nrfx_drv_state_t state;
+ volatile bool transfer_in_progress;
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ bool use_hw_ss;
+#endif
+
+ // [no need for 'volatile' attribute for the following members, as they
+ // are not concurrently used in IRQ handlers and main line code]
+ bool ss_active_high;
+ uint8_t ss_pin;
+ uint8_t miso_pin;
+ uint8_t orc;
+
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ size_t tx_length;
+ size_t rx_length;
+#endif
+} spim_control_block_t;
+static spim_control_block_t m_cb[NRFX_SPIM_ENABLED_COUNT];
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+
+// Workaround for nRF52840 anomaly 198: SPIM3 transmit data might be corrupted.
+
+static uint32_t m_anomaly_198_preserved_value;
+
+static void anomaly_198_enable(uint8_t const * p_buffer, size_t buf_len)
+{
+ m_anomaly_198_preserved_value = *((volatile uint32_t *)0x40000E00);
+
+ if (buf_len == 0)
+ {
+ return;
+ }
+ uint32_t buffer_end_addr = ((uint32_t)p_buffer) + buf_len;
+ uint32_t block_addr = ((uint32_t)p_buffer) & ~0x1FFF;
+ uint32_t block_flag = (1UL << ((block_addr >> 13) & 0xFFFF));
+ uint32_t occupied_blocks = 0;
+
+ if (block_addr >= 0x20010000)
+ {
+ occupied_blocks = (1UL << 8);
+ }
+ else
+ {
+ do {
+ occupied_blocks |= block_flag;
+ block_flag <<= 1;
+ block_addr += 0x2000;
+ } while ((block_addr < buffer_end_addr) && (block_addr < 0x20012000));
+ }
+
+ *((volatile uint32_t *)0x40000E00) = occupied_blocks;
+}
+
+static void anomaly_198_disable(void)
+{
+ *((volatile uint32_t *)0x40000E00) = m_anomaly_198_preserved_value;
+}
+#endif // NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+
+nrfx_err_t nrfx_spim_init(nrfx_spim_t const * const p_instance,
+ nrfx_spim_config_t const * p_config,
+ nrfx_spim_evt_handler_t handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+
+ // Currently, only SPIM3 in nRF52840 supports the extended features. Other instances must be checked.
+ if ((p_instance->drv_inst_idx != NRFX_SPIM3_INST_IDX) &&
+ ((p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED) ||
+ (p_config->frequency == NRF_SPIM_FREQ_16M) ||
+ (p_config->frequency == NRF_SPIM_FREQ_32M) ||
+ (p_config->rx_delay != 0x00) ||
+ (p_config->use_hw_ss)))
+ {
+ err_code = NRFX_ERROR_NOT_SUPPORTED;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif
+
+ NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_SPIM_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+ nrfx_spim_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+ nrfx_spim_1_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+ nrfx_spim_2_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+ nrfx_spim_3_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_reg,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ p_cb->handler = handler;
+ p_cb->p_context = p_context;
+
+ uint32_t mosi_pin;
+ uint32_t miso_pin;
+ // Configure pins used by the peripheral:
+ // - SCK - output with initial value corresponding with the SPI mode used:
+ // 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1);
+ // according to the reference manual guidelines this pin and its input
+ // buffer must always be connected for the SPI to work.
+ if (p_config->mode <= NRF_SPIM_MODE_1)
+ {
+ nrf_gpio_pin_clear(p_config->sck_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_set(p_config->sck_pin);
+ }
+ nrf_gpio_cfg(p_config->sck_pin,
+ NRF_GPIO_PIN_DIR_OUTPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+ // - MOSI (optional) - output with initial value 0,
+ if (p_config->mosi_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+ mosi_pin = p_config->mosi_pin;
+ nrf_gpio_pin_clear(mosi_pin);
+ nrf_gpio_cfg_output(mosi_pin);
+ }
+ else
+ {
+ mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED;
+ }
+ // - MISO (optional) - input,
+ if (p_config->miso_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+ miso_pin = p_config->miso_pin;
+ nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRFX_SPIM_MISO_PULL_CFG);
+ }
+ else
+ {
+ miso_pin = NRF_SPIM_PIN_NOT_CONNECTED;
+ }
+ m_cb[p_instance->drv_inst_idx].miso_pin = p_config->miso_pin;
+ // - Slave Select (optional) - output with initial value 1 (inactive).
+ if (p_config->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+ if (p_config->ss_active_high)
+ {
+ nrf_gpio_pin_clear(p_config->ss_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_set(p_config->ss_pin);
+ }
+ nrf_gpio_cfg_output(p_config->ss_pin);
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ if (p_config->use_hw_ss)
+ {
+ m_cb[p_instance->drv_inst_idx].use_hw_ss = p_config->use_hw_ss;
+ nrf_spim_csn_configure(p_spim,
+ p_config->ss_pin,
+ (p_config->ss_active_high == true ?
+ NRF_SPIM_CSN_POL_HIGH : NRF_SPIM_CSN_POL_LOW),
+ p_config->ss_duration);
+ }
+#endif
+ m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin;
+ m_cb[p_instance->drv_inst_idx].ss_active_high = p_config->ss_active_high;
+ }
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ // - DCX (optional) - output.
+ if (p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+ nrf_gpio_pin_set(p_config->dcx_pin);
+ nrf_gpio_cfg_output(p_config->dcx_pin);
+ nrf_spim_dcx_pin_set(p_spim, p_config->dcx_pin);
+ }
+
+ // Change rx delay
+ nrf_spim_iftiming_set(p_spim, p_config->rx_delay);
+#endif
+
+
+ nrf_spim_pins_set(p_spim, p_config->sck_pin, mosi_pin, miso_pin);
+ nrf_spim_frequency_set(p_spim, p_config->frequency);
+ nrf_spim_configure(p_spim, p_config->mode, p_config->bit_order);
+
+ nrf_spim_orc_set(p_spim, p_config->orc);
+
+ if (p_cb->handler)
+ {
+ nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
+ }
+
+ nrf_spim_enable(p_spim);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
+ p_config->irq_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
+ }
+
+ p_cb->transfer_in_progress = false;
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_spim_uninit(nrfx_spim_t const * const p_instance)
+{
+ spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
+ }
+
+ NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+ if (p_cb->handler)
+ {
+ nrf_spim_int_disable(p_spim, NRF_SPIM_ALL_INTS_MASK);
+ if (p_cb->transfer_in_progress)
+ {
+ // Ensure that SPI is not performing any transfer.
+ nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP);
+ while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED))
+ {}
+ p_cb->transfer_in_progress = false;
+ }
+ }
+
+ if (p_cb->miso_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+ nrf_gpio_cfg_default(p_cb->miso_pin);
+ }
+ nrf_spim_disable(p_spim);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_reg);
+#endif
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * const p_instance,
+ nrfx_spim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags,
+ uint8_t cmd_length)
+{
+ NRFX_ASSERT(cmd_length <= NRF_SPIM_DCX_CNT_ALL_CMD);
+ nrf_spim_dcx_cnt_set((NRF_SPIM_Type *)p_instance->p_reg, cmd_length);
+ return nrfx_spim_xfer(p_instance, p_xfer_desc, 0);
+}
+#endif
+
+static void finish_transfer(spim_control_block_t * p_cb)
+{
+ // If Slave Select signal is used, this is the time to deactivate it.
+ if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ if (!p_cb->use_hw_ss)
+#endif
+ {
+ if (p_cb->ss_active_high)
+ {
+ nrf_gpio_pin_clear(p_cb->ss_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_set(p_cb->ss_pin);
+ }
+ }
+ }
+
+ // By clearing this flag before calling the handler we allow subsequent
+ // transfers to be started directly from the handler function.
+ p_cb->transfer_in_progress = false;
+
+ p_cb->evt.type = NRFX_SPIM_EVENT_DONE;
+ p_cb->handler(&p_cb->evt, p_cb->p_context);
+}
+
+__STATIC_INLINE void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable)
+{
+ if (!enable)
+ {
+ nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
+ }
+ else
+ {
+ nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
+ }
+}
+
+__STATIC_INLINE void spim_list_enable_handle(NRF_SPIM_Type * p_spim, uint32_t flags)
+{
+ if (NRFX_SPIM_FLAG_TX_POSTINC & flags)
+ {
+ nrf_spim_tx_list_enable(p_spim);
+ }
+ else
+ {
+ nrf_spim_tx_list_disable(p_spim);
+ }
+
+ if (NRFX_SPIM_FLAG_RX_POSTINC & flags)
+ {
+ nrf_spim_rx_list_enable(p_spim);
+ }
+ else
+ {
+ nrf_spim_rx_list_disable(p_spim);
+ }
+}
+
+static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim,
+ spim_control_block_t * p_cb,
+ nrfx_spim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+ nrfx_err_t err_code;
+ // EasyDMA requires that transfer buffers are placed in Data RAM region;
+ // signal error if they are not.
+ if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
+ (p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
+ {
+ p_cb->transfer_in_progress = false;
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ p_cb->tx_length = 0;
+ p_cb->rx_length = 0;
+#endif
+
+ nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+ nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+ if (p_spim == NRF_SPIM3)
+ {
+ anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+ }
+#endif
+
+ nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+
+ spim_list_enable_handle(p_spim, flags);
+
+ if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
+ {
+ nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+ }
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
+ {
+ nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
+ p_cb->tx_length = p_xfer_desc->tx_length;
+ p_cb->rx_length = p_xfer_desc->rx_length;
+ nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
+ nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
+ nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
+ }
+#endif
+
+ if (!p_cb->handler)
+ {
+ while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){}
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+ if (p_spim == NRF_SPIM3)
+ {
+ anomaly_198_disable();
+ }
+#endif
+ if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ if (!p_cb->use_hw_ss)
+#endif
+ {
+ if (p_cb->ss_active_high)
+ {
+ nrf_gpio_pin_clear(p_cb->ss_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_set(p_cb->ss_pin);
+ }
+ }
+ }
+ }
+ else
+ {
+ spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
+ }
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * const p_instance,
+ nrfx_spim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+ spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
+ NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
+ NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
+ p_xfer_desc->rx_length,
+ p_xfer_desc->tx_length));
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (p_cb->transfer_in_progress)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
+ NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
+ {
+ p_cb->transfer_in_progress = true;
+ }
+ }
+
+ p_cb->evt.xfer_desc = *p_xfer_desc;
+
+ if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+ {
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+ if (!p_cb->use_hw_ss)
+#endif
+ {
+ if (p_cb->ss_active_high)
+ {
+ nrf_gpio_pin_set(p_cb->ss_pin);
+ }
+ else
+ {
+ nrf_gpio_pin_clear(p_cb->ss_pin);
+ }
+ }
+ }
+
+ return spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags);
+}
+
+void nrfx_spim_abort(nrfx_spim_t const * p_instance)
+{
+ spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrf_spim_task_trigger(p_instance->p_reg, NRF_SPIM_TASK_STOP);
+ while (!nrf_spim_event_check(p_instance->p_reg, NRF_SPIM_EVENT_STOPPED))
+ {}
+ p_cb->transfer_in_progress = false;
+}
+
+uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance)
+{
+ NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+ return nrf_spim_task_address_get(p_spim, NRF_SPIM_TASK_START);
+}
+
+uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance)
+{
+ NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+ return nrf_spim_event_address_get(p_spim, NRF_SPIM_EVENT_END);
+}
+
+static void irq_handler(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
+{
+
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ if ((nrf_spim_int_enable_check(p_spim, NRF_SPIM_INT_STARTED_MASK)) &&
+ (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STARTED)) )
+ {
+ /* Handle first, zero-length, auxiliary transmission. */
+ nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
+ nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+
+ NRFX_ASSERT(p_spim->TXD.MAXCNT == 0);
+ p_spim->TXD.MAXCNT = p_cb->tx_length;
+
+ NRFX_ASSERT(p_spim->RXD.MAXCNT == 0);
+ p_spim->RXD.MAXCNT = p_cb->rx_length;
+
+ /* Disable STARTED interrupt, used only in auxiliary transmission. */
+ nrf_spim_int_disable(p_spim, NRF_SPIM_INT_STARTED_MASK);
+
+ /* Start the actual, glitch-free transmission. */
+ nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+ return;
+ }
+#endif
+
+ if (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
+ {
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+ if (p_spim == NRF_SPIM3)
+ {
+ anomaly_198_disable();
+ }
+#endif
+ nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+ NRFX_ASSERT(p_cb->handler);
+ NRFX_LOG_DEBUG("Event: NRF_SPIM_EVENT_END.");
+ finish_transfer(p_cb);
+ }
+}
+
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+void nrfx_spim_0_irq_handler(void)
+{
+ irq_handler(NRF_SPIM0, &m_cb[NRFX_SPIM0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+void nrfx_spim_1_irq_handler(void)
+{
+ irq_handler(NRF_SPIM1, &m_cb[NRFX_SPIM1_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+void nrfx_spim_2_irq_handler(void)
+{
+ irq_handler(NRF_SPIM2, &m_cb[NRFX_SPIM2_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+void nrfx_spim_3_irq_handler(void)
+{
+ irq_handler(NRF_SPIM3, &m_cb[NRFX_SPIM3_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_SPIM_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spis.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spis.c
new file mode 100644
index 0000000..53075f0
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_spis.c
@@ -0,0 +1,494 @@
+/**
+ * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SPIS_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_SPIS0_ENABLED) || NRFX_CHECK(NRFX_SPIS1_ENABLED) || \
+ NRFX_CHECK(NRFX_SPIS2_ENABLED))
+#error "No enabled SPIS instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_spis.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE SPIS
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_SPIS_EVENT_ACQUIRED ? "NRF_SPIS_EVENT_ACQUIRED" : \
+ (event == NRF_SPIS_EVENT_END ? "NRF_SPIS_EVENT_END" : \
+ "UNKNOWN ERROR"))
+
+#define SPISX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
+ (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+ NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
+
+#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
+#define SPIS0_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS0, __VA_ARGS__)
+#else
+#define SPIS0_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
+#define SPIS1_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS1, __VA_ARGS__)
+#else
+#define SPIS1_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
+#define SPIS2_LENGTH_VALIDATE(...) SPISX_LENGTH_VALIDATE(SPIS2, __VA_ARGS__)
+#else
+#define SPIS2_LENGTH_VALIDATE(...) 0
+#endif
+
+#define SPIS_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) \
+ (SPIS0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+ SPIS1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+ SPIS2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
+
+
+#if NRFX_CHECK(NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+#include <nrfx_gpiote.h>
+#define USE_DMA_ISSUE_WORKAROUND
+// This handler is called by the GPIOTE driver when a falling edge is detected
+// on the CSN line. There is no need to do anything here. The handling of the
+// interrupt itself provides a protection for DMA transfers.
+static void csn_event_handler(nrfx_gpiote_pin_t pin,
+ nrf_gpiote_polarity_t action)
+{
+}
+#endif
+
+
+/**@brief States of the SPI transaction state machine. */
+typedef enum
+{
+ SPIS_STATE_INIT, /**< Initialization state. In this state the module waits for a call to @ref spi_slave_buffers_set. */
+ SPIS_BUFFER_RESOURCE_REQUESTED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has started. */
+ SPIS_BUFFER_RESOURCE_CONFIGURED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has completed. */
+ SPIS_XFER_COMPLETED /**< State where SPI transaction has been completed. */
+} nrfx_spis_state_t;
+
+/**@brief SPIS control block - driver instance local data. */
+typedef struct
+{
+ volatile uint32_t tx_buffer_size; //!< SPI slave TX buffer size in bytes.
+ volatile uint32_t rx_buffer_size; //!< SPI slave RX buffer size in bytes.
+ nrfx_spis_event_handler_t handler; //!< SPI event handler.
+ volatile const uint8_t * tx_buffer; //!< SPI slave TX buffer.
+ volatile uint8_t * rx_buffer; //!< SPI slave RX buffer.
+ nrfx_drv_state_t state; //!< driver initialization state.
+ volatile nrfx_spis_state_t spi_state; //!< SPI slave state.
+ void * p_context; //!< Context set on initialization.
+} spis_cb_t;
+
+static spis_cb_t m_cb[NRFX_SPIS_ENABLED_COUNT];
+
+nrfx_err_t nrfx_spis_init(nrfx_spis_t const * const p_instance,
+ nrfx_spis_config_t const * p_config,
+ nrfx_spis_event_handler_t event_handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(event_handler);
+ spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ NRF_SPIS_Type * p_spis = p_instance->p_reg;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if ((uint32_t)p_config->mode > (uint32_t)NRF_SPIS_MODE_3)
+ {
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_SPIS_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_SPIS0_ENABLED)
+ nrfx_spis_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPIS1_ENABLED)
+ nrfx_spis_1_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_SPIS2_ENABLED)
+ nrfx_spis_2_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_spis,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ // Configure the SPI pins for input.
+ uint32_t mosi_pin;
+ uint32_t miso_pin;
+
+ if (p_config->miso_pin != NRFX_SPIS_PIN_NOT_USED)
+ {
+ nrf_gpio_cfg(p_config->miso_pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ p_config->miso_drive,
+ NRF_GPIO_PIN_NOSENSE);
+ miso_pin = p_config->miso_pin;
+ }
+ else
+ {
+ miso_pin = NRF_SPIS_PIN_NOT_CONNECTED;
+ }
+
+ if (p_config->mosi_pin != NRFX_SPIS_PIN_NOT_USED)
+ {
+ nrf_gpio_cfg(p_config->mosi_pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+ mosi_pin = p_config->mosi_pin;
+ }
+ else
+ {
+ mosi_pin = NRF_SPIS_PIN_NOT_CONNECTED;
+ }
+
+ nrf_gpio_cfg(p_config->csn_pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ p_config->csn_pullup,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+
+ nrf_gpio_cfg(p_config->sck_pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ NRF_GPIO_PIN_INPUT_CONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+
+ nrf_spis_pins_set(p_spis, p_config->sck_pin, mosi_pin, miso_pin, p_config->csn_pin);
+
+ nrf_spis_rx_buffer_set(p_spis, NULL, 0);
+ nrf_spis_tx_buffer_set(p_spis, NULL, 0);
+
+ // Configure SPI mode.
+ nrf_spis_configure(p_spis, p_config->mode, p_config->bit_order);
+
+ // Configure DEF and ORC characters.
+ nrf_spis_def_set(p_spis, p_config->def);
+ nrf_spis_orc_set(p_spis, p_config->orc);
+
+ // Clear possible pending events.
+ nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
+ nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
+
+ // Enable END_ACQUIRE shortcut.
+ nrf_spis_shorts_enable(p_spis, NRF_SPIS_SHORT_END_ACQUIRE);
+
+ p_cb->spi_state = SPIS_STATE_INIT;
+ p_cb->handler = event_handler;
+ p_cb->p_context = p_context;
+
+#if defined(USE_DMA_ISSUE_WORKAROUND)
+ // Configure a GPIOTE channel to generate interrupts on each falling edge
+ // on the CSN line. Handling of these interrupts will make the CPU active,
+ // and thus will protect the DMA transfers started by SPIS right after it
+ // is selected for communication.
+ // [the GPIOTE driver may be already initialized at this point (by this
+ // driver when another SPIS instance is used, or by an application code),
+ // so just ignore the returned value]
+ (void)nrfx_gpiote_init();
+ static nrfx_gpiote_in_config_t const csn_gpiote_config =
+ NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
+ nrfx_err_t gpiote_err_code = nrfx_gpiote_in_init(p_config->csn_pin,
+ &csn_gpiote_config, csn_event_handler);
+ if (gpiote_err_code != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_INTERNAL;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ nrfx_gpiote_in_event_enable(p_config->csn_pin, true);
+#endif
+
+ // Enable IRQ.
+ nrf_spis_int_enable(p_spis, NRF_SPIS_INT_ACQUIRED_MASK |
+ NRF_SPIS_INT_END_MASK);
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
+ p_config->irq_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ // Enable SPI slave device.
+ nrf_spis_enable(p_spis);
+
+ NRFX_LOG_INFO("Initialized.");
+ return NRFX_SUCCESS;
+}
+
+
+void nrfx_spis_uninit(nrfx_spis_t const * const p_instance)
+{
+ spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ NRF_SPIS_Type * p_spis = p_instance->p_reg;
+
+ #define DISABLE_ALL 0xFFFFFFFF
+ nrf_spis_disable(p_spis);
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
+ nrf_spis_int_disable(p_spis, DISABLE_ALL);
+ #undef DISABLE_ALL
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_spis);
+#endif
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized.");
+}
+
+
+/**@brief Function for executing the state entry action. */
+static void spis_state_entry_action_execute(NRF_SPIS_Type * p_spis,
+ spis_cb_t * p_cb)
+{
+ nrfx_spis_evt_t event;
+
+ switch (p_cb->spi_state)
+ {
+ case SPIS_BUFFER_RESOURCE_REQUESTED:
+ nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_ACQUIRE);
+ break;
+
+ case SPIS_BUFFER_RESOURCE_CONFIGURED:
+ event.evt_type = NRFX_SPIS_BUFFERS_SET_DONE;
+ event.rx_amount = 0;
+ event.tx_amount = 0;
+
+ NRFX_ASSERT(p_cb->handler != NULL);
+ p_cb->handler(&event, p_cb->p_context);
+ break;
+
+ case SPIS_XFER_COMPLETED:
+ event.evt_type = NRFX_SPIS_XFER_DONE;
+ event.rx_amount = nrf_spis_rx_amount_get(p_spis);
+ event.tx_amount = nrf_spis_tx_amount_get(p_spis);
+ NRFX_LOG_INFO("Transfer rx_len:%d.", event.rx_amount);
+ NRFX_LOG_DEBUG("Rx data:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)p_cb->rx_buffer,
+ event.rx_amount * sizeof(p_cb->rx_buffer[0]));
+ NRFX_ASSERT(p_cb->handler != NULL);
+ p_cb->handler(&event, p_cb->p_context);
+ break;
+
+ default:
+ // No implementation required.
+ break;
+ }
+}
+
+/**@brief Function for changing the state of the SPI state machine.
+ *
+ * @param[in] p_spis SPIS instance register.
+ * @param[in] p_cb SPIS instance control block.
+ * @param[in] new_state State where the state machine transits to.
+ */
+static void spis_state_change(NRF_SPIS_Type * p_spis,
+ spis_cb_t * p_cb,
+ nrfx_spis_state_t new_state)
+{
+ p_cb->spi_state = new_state;
+ spis_state_entry_action_execute(p_spis, p_cb);
+}
+
+nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * const p_instance,
+ uint8_t const * p_tx_buffer,
+ size_t tx_buffer_length,
+ uint8_t * p_rx_buffer,
+ size_t rx_buffer_length)
+{
+ NRFX_ASSERT(p_tx_buffer != NULL || tx_buffer_length == 0);
+ NRFX_ASSERT(p_rx_buffer != NULL || rx_buffer_length == 0);
+
+ spis_cb_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ if (!SPIS_LENGTH_VALIDATE(p_instance->drv_inst_idx,
+ rx_buffer_length,
+ tx_buffer_length))
+ {
+ return NRFX_ERROR_INVALID_LENGTH;
+ }
+
+ // EasyDMA requires that transfer buffers are placed in Data RAM region;
+ // signal error if they are not.
+ if ((p_tx_buffer != NULL && !nrfx_is_in_ram(p_tx_buffer)) ||
+ (p_rx_buffer != NULL && !nrfx_is_in_ram(p_rx_buffer)))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ switch (p_cb->spi_state)
+ {
+ case SPIS_STATE_INIT:
+ case SPIS_XFER_COMPLETED:
+ case SPIS_BUFFER_RESOURCE_CONFIGURED:
+ p_cb->tx_buffer = p_tx_buffer;
+ p_cb->rx_buffer = p_rx_buffer;
+ p_cb->tx_buffer_size = tx_buffer_length;
+ p_cb->rx_buffer_size = rx_buffer_length;
+ err_code = NRFX_SUCCESS;
+
+ spis_state_change(p_instance->p_reg, p_cb, SPIS_BUFFER_RESOURCE_REQUESTED);
+ break;
+
+ case SPIS_BUFFER_RESOURCE_REQUESTED:
+ err_code = NRFX_ERROR_INVALID_STATE;
+ break;
+
+ default:
+ // @note: execution of this code path would imply internal error in the design.
+ err_code = NRFX_ERROR_INTERNAL;
+ break;
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb)
+{
+ // @note: as multiple events can be pending for processing, the correct event processing order
+ // is as follows:
+ // - SPI semaphore acquired event.
+ // - SPI transaction complete event.
+
+ // Check for SPI semaphore acquired event.
+ if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED))
+ {
+ nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
+ NRFX_LOG_DEBUG("SPIS: Event: %s.", EVT_TO_STR(NRF_SPIS_EVENT_ACQUIRED));
+
+ switch (p_cb->spi_state)
+ {
+ case SPIS_BUFFER_RESOURCE_REQUESTED:
+ nrf_spis_tx_buffer_set(p_spis, (uint8_t *)p_cb->tx_buffer, p_cb->tx_buffer_size);
+ nrf_spis_rx_buffer_set(p_spis, (uint8_t *)p_cb->rx_buffer, p_cb->rx_buffer_size);
+
+ nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE);
+
+ spis_state_change(p_spis, p_cb, SPIS_BUFFER_RESOURCE_CONFIGURED);
+ break;
+
+ default:
+ // No implementation required.
+ break;
+ }
+ }
+
+ // Check for SPI transaction complete event.
+ if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END))
+ {
+ nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
+ NRFX_LOG_DEBUG("SPIS: Event: %s.", EVT_TO_STR(NRF_SPIS_EVENT_END));
+
+ switch (p_cb->spi_state)
+ {
+ case SPIS_BUFFER_RESOURCE_CONFIGURED:
+ spis_state_change(p_spis, p_cb, SPIS_XFER_COMPLETED);
+ break;
+
+ default:
+ // No implementation required.
+ break;
+ }
+ }
+}
+
+#if NRFX_CHECK(NRFX_SPIS0_ENABLED)
+void nrfx_spis_0_irq_handler(void)
+{
+ spis_irq_handler(NRF_SPIS0, &m_cb[NRFX_SPIS0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIS1_ENABLED)
+void nrfx_spis_1_irq_handler(void)
+{
+ spis_irq_handler(NRF_SPIS1, &m_cb[NRFX_SPIS1_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIS2_ENABLED)
+void nrfx_spis_2_irq_handler(void)
+{
+ spis_irq_handler(NRF_SPIS2, &m_cb[NRFX_SPIS2_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_SPIS_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_swi.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_swi.c
new file mode 100644
index 0000000..4a6dcc4
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_swi.c
@@ -0,0 +1,412 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SWI_ENABLED)
+
+#include <nrfx_swi.h>
+
+#define NRFX_LOG_MODULE SWI
+#include <nrfx_log.h>
+
+
+// NRFX_SWI_RESERVED_MASK - SWIs reserved for use by external modules.
+#if NRFX_CHECK(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+#define NRFX_SWI_RESERVED_MASK ((NRFX_SWI_USED) | \
+ (1u << NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE))
+#else
+#define NRFX_SWI_RESERVED_MASK (NRFX_SWI_USED)
+#endif
+
+// NRFX_SWI_DISABLED_MASK - SWIs excluded from use in <nrfx_config.h>.
+#if NRFX_CHECK(NRFX_SWI0_DISABLED)
+#define NRFX_SWI0_DISABLED_MASK (1u << 0)
+#else
+#define NRFX_SWI0_DISABLED_MASK 0u
+#endif
+#if NRFX_CHECK(NRFX_SWI1_DISABLED)
+#define NRFX_SWI1_DISABLED_MASK (1u << 1)
+#else
+#define NRFX_SWI1_DISABLED_MASK 0u
+#endif
+#if NRFX_CHECK(NRFX_SWI2_DISABLED)
+#define NRFX_SWI2_DISABLED_MASK (1u << 2)
+#else
+#define NRFX_SWI2_DISABLED_MASK 0u
+#endif
+#if NRFX_CHECK(NRFX_SWI3_DISABLED)
+#define NRFX_SWI3_DISABLED_MASK (1u << 3)
+#else
+#define NRFX_SWI3_DISABLED_MASK 0u
+#endif
+#if NRFX_CHECK(NRFX_SWI4_DISABLED)
+#define NRFX_SWI4_DISABLED_MASK (1u << 4)
+#else
+#define NRFX_SWI4_DISABLED_MASK 0u
+#endif
+#if NRFX_CHECK(NRFX_SWI5_DISABLED)
+#define NRFX_SWI5_DISABLED_MASK (1u << 5)
+#else
+#define NRFX_SWI5_DISABLED_MASK 0u
+#endif
+#define NRFX_SWI_DISABLED_MASK (NRFX_SWI0_DISABLED_MASK | \
+ NRFX_SWI1_DISABLED_MASK | \
+ NRFX_SWI2_DISABLED_MASK | \
+ NRFX_SWI3_DISABLED_MASK | \
+ NRFX_SWI4_DISABLED_MASK | \
+ NRFX_SWI5_DISABLED_MASK)
+
+#if (NRFX_SWI_RESERVED_MASK & NRFX_SWI_DISABLED_MASK)
+#error "A reserved SWI configured to be disabled. Check <nrfx_config.h> and NRFX_SWI_USED."
+#endif
+
+// NRFX_SWI_AVAILABLE_MASK - SWIs available for this module, i.e. present
+// in the hardware and neither reserved by external modules nor disabled
+// in <nrfx_config.h>.
+#define NRFX_SWI_PRESENT_MASK ((1u << (SWI_COUNT)) - 1u)
+#define NRFX_SWI_AVAILABLE_MASK (NRFX_SWI_PRESENT_MASK & \
+ ~(NRFX_SWI_RESERVED_MASK | \
+ NRFX_SWI_DISABLED_MASK))
+
+#if (NRFX_SWI_AVAILABLE_MASK == 0)
+#error "No available SWI instances. Check <nrfx_config.h> and NRFX_SWI_USED."
+#endif
+
+#define NRFX_SWI_IS_AVAILABLE(idx) ((NRFX_SWI_AVAILABLE_MASK >> (idx)) & 1u)
+
+#define NRFX_SWI_FIRST (NRFX_SWI_IS_AVAILABLE(0) ? 0u : \
+ (NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
+ (NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
+ (NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
+ (NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
+ 5u)))))
+#define NRFX_SWI_LAST (NRFX_SWI_IS_AVAILABLE(5) ? 5u : \
+ (NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
+ (NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
+ (NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
+ (NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
+ 0u)))))
+
+// NRFX_SWI_EGU_COUNT - number of EGU instances to be used by this module
+// (note - if EGU is not present, EGU_COUNT is not defined).
+#if NRFX_CHECK(NRFX_EGU_ENABLED)
+#define NRFX_SWI_EGU_COUNT EGU_COUNT
+#else
+#define NRFX_SWI_EGU_COUNT 0
+#endif
+
+// These flags are needed only for SWIs that have no corresponding EGU unit
+// (in EGU such flags are available in hardware).
+#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
+static nrfx_swi_flags_t m_swi_flags[SWI_COUNT - NRFX_SWI_EGU_COUNT];
+#endif
+static nrfx_swi_handler_t m_swi_handlers[SWI_COUNT];
+static uint8_t m_swi_allocated_mask;
+
+
+static void swi_mark_allocated(nrfx_swi_t swi)
+{
+ m_swi_allocated_mask |= (1u << swi);
+}
+
+static void swi_mark_unallocated(nrfx_swi_t swi)
+{
+ m_swi_allocated_mask &= ~(1u << swi);
+}
+
+static bool swi_is_allocated(nrfx_swi_t swi)
+{
+ return (m_swi_allocated_mask & (1u << swi));
+}
+
+static bool swi_is_available(nrfx_swi_t swi)
+{
+ return NRFX_SWI_IS_AVAILABLE(swi);
+}
+
+static IRQn_Type swi_irq_number_get(nrfx_swi_t swi)
+{
+ return (IRQn_Type)((uint32_t)SWI0_IRQn + (uint32_t)swi);
+}
+
+static void swi_handler_setup(nrfx_swi_t swi,
+ nrfx_swi_handler_t event_handler,
+ uint32_t irq_priority)
+{
+ m_swi_handlers[swi] = event_handler;
+
+#if NRFX_SWI_EGU_COUNT
+ if (swi < NRFX_SWI_EGU_COUNT)
+ {
+ NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
+ NRFX_ASSERT(p_egu != NULL);
+ nrf_egu_int_enable(p_egu, NRF_EGU_INT_ALL);
+
+ if (event_handler == NULL)
+ {
+ return;
+ }
+ }
+#endif
+
+ NRFX_ASSERT(event_handler != NULL);
+
+ NRFX_IRQ_PRIORITY_SET(swi_irq_number_get(swi), irq_priority);
+ NRFX_IRQ_ENABLE(swi_irq_number_get(swi));
+}
+
+nrfx_err_t nrfx_swi_alloc(nrfx_swi_t * p_swi,
+ nrfx_swi_handler_t event_handler,
+ uint32_t irq_priority)
+{
+ NRFX_ASSERT(p_swi != NULL);
+
+ nrfx_err_t err_code;
+
+ for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
+ {
+ if (swi_is_available(swi))
+ {
+ bool allocated = false;
+ NRFX_CRITICAL_SECTION_ENTER();
+ if (!swi_is_allocated(swi))
+ {
+ swi_mark_allocated(swi);
+ allocated = true;
+ }
+ NRFX_CRITICAL_SECTION_EXIT();
+
+ if (allocated)
+ {
+ swi_handler_setup(swi, event_handler, irq_priority);
+
+ *p_swi = swi;
+ NRFX_LOG_INFO("SWI channel allocated: %d.", (*p_swi));
+ return NRFX_SUCCESS;
+ }
+ }
+ }
+
+ err_code = NRFX_ERROR_NO_MEM;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+bool nrfx_swi_is_allocated(nrfx_swi_t swi)
+{
+ return swi_is_allocated(swi);
+}
+
+void nrfx_swi_free(nrfx_swi_t * p_swi)
+{
+ NRFX_ASSERT(p_swi != NULL);
+ nrfx_swi_t swi = *p_swi;
+
+ NRFX_ASSERT(swi_is_allocated(swi));
+ NRFX_IRQ_DISABLE(swi_irq_number_get(swi));
+ m_swi_handlers[swi] = NULL;
+
+ swi_mark_unallocated(swi);
+ *p_swi = NRFX_SWI_UNALLOCATED;
+}
+
+void nrfx_swi_all_free(void)
+{
+ for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
+ {
+ if (swi_is_allocated(swi))
+ {
+ NRFX_IRQ_DISABLE(swi_irq_number_get(swi));
+ m_swi_handlers[swi] = NULL;
+#if NRFX_SWI_EGU_COUNT
+ if (swi < NRFX_SWI_EGU_COUNT)
+ {
+ nrf_egu_int_disable(nrfx_swi_egu_instance_get(swi),
+ NRF_EGU_INT_ALL);
+ }
+#endif
+ }
+ }
+
+ m_swi_allocated_mask = 0;
+}
+
+void nrfx_swi_trigger(nrfx_swi_t swi, uint8_t flag_number)
+{
+ NRFX_ASSERT(swi_is_allocated(swi));
+
+#if NRFX_SWI_EGU_COUNT
+
+ NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
+#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
+ if (p_egu == NULL)
+ {
+ m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
+ NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
+ }
+ else
+#endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
+ {
+ nrf_egu_task_trigger(p_egu,
+ nrf_egu_task_trigger_get(p_egu, flag_number));
+ }
+
+#else // -> #if !NRFX_SWI_EGU_COUNT
+
+ m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
+ NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
+
+#endif
+}
+
+#if NRFX_SWI_EGU_COUNT
+static void egu_irq_handler(nrfx_swi_t swi, uint8_t egu_channel_count)
+{
+#if (NRFX_SWI_FIRST > 0)
+ NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
+#endif
+ NRFX_ASSERT(swi <= NRFX_SWI_LAST);
+ nrfx_swi_handler_t handler = m_swi_handlers[swi];
+ NRFX_ASSERT(handler != NULL);
+
+ NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
+ NRFX_ASSERT(p_egu != NULL);
+
+ nrfx_swi_flags_t flags = 0;
+ for (uint8_t i = 0; i < egu_channel_count; ++i)
+ {
+ nrf_egu_event_t egu_event = nrf_egu_event_triggered_get(p_egu, i);
+ if (nrf_egu_event_check(p_egu, egu_event))
+ {
+ flags |= (1u << i);
+ nrf_egu_event_clear(p_egu, egu_event);
+ }
+ }
+
+ handler(swi, flags);
+}
+#endif // NRFX_SWI_EGU_COUNT
+
+#if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
+static void swi_irq_handler(nrfx_swi_t swi)
+{
+#if (NRFX_SWI_FIRST > 0)
+ NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
+#endif
+ NRFX_ASSERT(swi <= NRFX_SWI_LAST);
+ nrfx_swi_handler_t handler = m_swi_handlers[swi];
+ NRFX_ASSERT(handler != NULL);
+
+ nrfx_swi_flags_t flags = m_swi_flags[swi - NRFX_SWI_EGU_COUNT];
+ m_swi_flags[swi - NRFX_SWI_EGU_COUNT] &= ~flags;
+
+ handler(swi, flags);
+}
+#endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
+
+
+#if NRFX_SWI_IS_AVAILABLE(0)
+void nrfx_swi_0_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 0)
+ egu_irq_handler(0, EGU0_CH_NUM);
+#else
+ swi_irq_handler(0);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(0)
+
+#if NRFX_SWI_IS_AVAILABLE(1)
+void nrfx_swi_1_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 1)
+ egu_irq_handler(1, EGU1_CH_NUM);
+#else
+ swi_irq_handler(1);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(1)
+
+#if NRFX_SWI_IS_AVAILABLE(2)
+void nrfx_swi_2_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 2)
+ egu_irq_handler(2, EGU2_CH_NUM);
+#else
+ swi_irq_handler(2);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(2)
+
+#if NRFX_SWI_IS_AVAILABLE(3)
+void nrfx_swi_3_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 3)
+ egu_irq_handler(3, EGU3_CH_NUM);
+#else
+ swi_irq_handler(3);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(3)
+
+#if NRFX_SWI_IS_AVAILABLE(4)
+void nrfx_swi_4_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 4)
+ egu_irq_handler(4, EGU4_CH_NUM);
+#else
+ swi_irq_handler(4);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(4)
+
+#if NRFX_SWI_IS_AVAILABLE(5)
+void nrfx_swi_5_irq_handler(void)
+{
+#if (NRFX_SWI_EGU_COUNT > 5)
+ egu_irq_handler(5, EGU5_CH_NUM);
+#else
+ swi_irq_handler(5);
+#endif
+}
+#endif // NRFX_SWI_IS_AVAILABLE(5)
+
+#endif // NRFX_CHECK(NRFX_SWI_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_systick.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_systick.c
new file mode 100644
index 0000000..ef38b0f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_systick.c
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_SYSTICK_ENABLED)
+#include <nrfx_systick.h>
+
+/**
+ * @brief Maximum number of ticks to delay
+ *
+ * The maximum number of ticks should be much lower than
+ * Physical maximum count of the SysTick timer.
+ * It is dictated by the fact that it would be impossible to detect delay
+ * properly when the timer value warps around the starting point.
+ */
+#define NRFX_SYSTICK_TICKS_MAX (NRF_SYSTICK_VAL_MASK / 2UL)
+
+/**
+ * @brief Number of milliseconds in a second
+ */
+#define NRFX_SYSTICK_MS (1000UL)
+
+/**
+ * @brief Number of microseconds in a second
+ */
+#define NRFX_SYSTICK_US (1000UL * NRFX_SYSTICK_MS)
+
+/**
+ * @brief Number of milliseconds to wait in single loop
+ *
+ * Constant used by @ref nrd_drv_systick_delay_ms function
+ * to split waiting into loops and rest.
+ *
+ * It describes the number of milliseconds to wait in single loop.
+ *
+ * See @ref nrfx_systick_delay_ms source code for details.
+ */
+#define NRFX_SYSTICK_MS_STEP (64U)
+
+/**
+ * @brief Checks if the given time is in correct range
+ *
+ * Function tests given time is not to big for this library.
+ * Assertion is used for testing.
+ *
+ * @param us Time in microseconds to check
+ */
+#define NRFX_SYSTICK_ASSERT_TIMEOUT(us) \
+ NRFX_ASSERT(us <= (NRFX_SYSTICK_TICKS_MAX / ((SystemCoreClock) / NRFX_SYSTICK_US)));
+
+/**
+ * @brief Function that converts microseconds to ticks
+ *
+ * Function converts from microseconds to CPU ticks.
+ *
+ * @param us Number of microseconds
+ *
+ * @return Number of ticks
+ *
+ * @sa nrfx_systick_ms_tick
+ */
+static inline uint32_t nrfx_systick_us_tick(uint32_t us)
+{
+ return us * ((SystemCoreClock) / NRFX_SYSTICK_US);
+}
+
+/**
+ * @brief Function that converts milliseconds to ticks
+ *
+ * Function converts from milliseconds to CPU ticks.
+ *
+ * @param us Number of milliseconds
+ *
+ * @return Number of ticks
+ *
+ * @sa nrfx_systick_us_tick
+ */
+static inline uint32_t nrfx_systick_ms_tick(uint32_t ms)
+{
+ return ms * ((SystemCoreClock) / NRFX_SYSTICK_MS);
+}
+
+void nrfx_systick_init(void)
+{
+ nrf_systick_load_set(NRF_SYSTICK_VAL_MASK);
+ nrf_systick_csr_set(
+ NRF_SYSTICK_CSR_CLKSOURCE_CPU |
+ NRF_SYSTICK_CSR_TICKINT_DISABLE |
+ NRF_SYSTICK_CSR_ENABLE);
+}
+
+void nrfx_systick_get(nrfx_systick_state_t * p_state)
+{
+ p_state->time = nrf_systick_val_get();
+}
+
+bool nrfx_systick_test(nrfx_systick_state_t const * p_state, uint32_t us)
+{
+ NRFX_SYSTICK_ASSERT_TIMEOUT(us);
+
+ const uint32_t diff = NRF_SYSTICK_VAL_MASK & ((p_state->time) - nrf_systick_val_get());
+ return (diff >= nrfx_systick_us_tick(us));
+}
+
+void nrfx_systick_delay_ticks(uint32_t ticks)
+{
+ NRFX_ASSERT(ticks <= NRFX_SYSTICK_TICKS_MAX);
+
+ const uint32_t start = nrf_systick_val_get();
+ while ((NRF_SYSTICK_VAL_MASK & (start - nrf_systick_val_get())) < ticks)
+ {
+ /* Nothing to do */
+ }
+}
+
+void nrfx_systick_delay_us(uint32_t us)
+{
+ NRFX_SYSTICK_ASSERT_TIMEOUT(us);
+ nrfx_systick_delay_ticks(nrfx_systick_us_tick(us));
+}
+
+void nrfx_systick_delay_ms(uint32_t ms)
+{
+ uint32_t n = ms / NRFX_SYSTICK_MS_STEP;
+ uint32_t r = ms % NRFX_SYSTICK_MS_STEP;
+ while (0 != (n--))
+ {
+ nrfx_systick_delay_ticks(nrfx_systick_ms_tick(NRFX_SYSTICK_MS_STEP));
+ }
+ nrfx_systick_delay_ticks(nrfx_systick_ms_tick(r));
+}
+
+#endif // NRFX_CHECK(NRFX_SYSTICK_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_timer.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_timer.c
new file mode 100644
index 0000000..024958e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_timer.c
@@ -0,0 +1,330 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_TIMER_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_TIMER0_ENABLED) || NRFX_CHECK(NRFX_TIMER1_ENABLED) || \
+ NRFX_CHECK(NRFX_TIMER2_ENABLED) || NRFX_CHECK(NRFX_TIMER3_ENABLED) || \
+ NRFX_CHECK(NRFX_TIMER4_ENABLED))
+#error "No enabled TIMER instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_timer.h>
+
+#define NRFX_LOG_MODULE TIMER
+#include <nrfx_log.h>
+
+/**@brief Timer control block. */
+typedef struct
+{
+ nrfx_timer_event_handler_t handler;
+ void * context;
+ nrfx_drv_state_t state;
+} timer_control_block_t;
+
+static timer_control_block_t m_cb[NRFX_TIMER_ENABLED_COUNT];
+
+nrfx_err_t nrfx_timer_init(nrfx_timer_t const * const p_instance,
+ nrfx_timer_config_t const * p_config,
+ nrfx_timer_event_handler_t timer_event_handler)
+{
+ timer_control_block_t * p_cb = &m_cb[p_instance->instance_id];
+#ifdef SOFTDEVICE_PRESENT
+ NRFX_ASSERT(p_instance->p_reg != NRF_TIMER0);
+#endif
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(timer_event_handler);
+
+ nrfx_err_t err_code;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ /* Warning 685: Relational operator '<=' always evaluates to 'true'"
+ * Warning in NRF_TIMER_IS_BIT_WIDTH_VALID macro. Macro validate timers resolution.
+ * Not necessary in nRF52 based systems. Obligatory in nRF51 based systems.
+ */
+
+ /*lint -save -e685 */
+
+ NRFX_ASSERT(NRF_TIMER_IS_BIT_WIDTH_VALID(p_instance->p_reg, p_config->bit_width));
+
+ //lint -restore
+
+ p_cb->handler = timer_event_handler;
+ p_cb->context = p_config->p_context;
+
+ uint8_t i;
+ for (i = 0; i < p_instance->cc_channel_count; ++i)
+ {
+ nrf_timer_event_clear(p_instance->p_reg,
+ nrf_timer_compare_event_get(i));
+ }
+
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
+ p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
+
+ nrf_timer_mode_set(p_instance->p_reg, p_config->mode);
+ nrf_timer_bit_width_set(p_instance->p_reg, p_config->bit_width);
+ nrf_timer_frequency_set(p_instance->p_reg, p_config->frequency);
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_timer_uninit(nrfx_timer_t const * const p_instance)
+{
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
+
+ #define DISABLE_ALL UINT32_MAX
+ nrf_timer_shorts_disable(p_instance->p_reg, DISABLE_ALL);
+ nrf_timer_int_disable(p_instance->p_reg, DISABLE_ALL);
+ #undef DISABLE_ALL
+
+ nrfx_timer_disable(p_instance);
+
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Uninitialized instance: %d.", p_instance->instance_id);
+}
+
+void nrfx_timer_enable(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START);
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled instance: %d.", p_instance->instance_id);
+}
+
+void nrfx_timer_disable(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_SHUTDOWN);
+ m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Disabled instance: %d.", p_instance->instance_id);
+}
+
+bool nrfx_timer_is_enabled(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ return (m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_POWERED_ON);
+}
+
+void nrfx_timer_resume(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START);
+ NRFX_LOG_INFO("Resumed instance: %d.", p_instance->instance_id);
+}
+
+void nrfx_timer_pause(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_STOP);
+ NRFX_LOG_INFO("Paused instance: %d.", p_instance->instance_id);
+}
+
+void nrfx_timer_clear(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_CLEAR);
+}
+
+void nrfx_timer_increment(nrfx_timer_t const * const p_instance)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(nrf_timer_mode_get(p_instance->p_reg) != NRF_TIMER_MODE_TIMER);
+
+ nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_COUNT);
+}
+
+uint32_t nrfx_timer_capture(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(cc_channel < p_instance->cc_channel_count);
+
+ nrf_timer_task_trigger(p_instance->p_reg,
+ nrf_timer_capture_task_get(cc_channel));
+ return nrf_timer_cc_read(p_instance->p_reg, cc_channel);
+}
+
+void nrfx_timer_compare(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel,
+ uint32_t cc_value,
+ bool enable_int)
+{
+ nrf_timer_int_mask_t timer_int = nrf_timer_compare_int_get(cc_channel);
+
+ if (enable_int)
+ {
+ nrf_timer_event_clear(p_instance->p_reg, nrf_timer_compare_event_get(cc_channel));
+ nrf_timer_int_enable(p_instance->p_reg, timer_int);
+ }
+ else
+ {
+ nrf_timer_int_disable(p_instance->p_reg, timer_int);
+ }
+
+ nrf_timer_cc_write(p_instance->p_reg, cc_channel, cc_value);
+ NRFX_LOG_INFO("Timer id: %d, capture value set: %lu, channel: %d.",
+ p_instance->instance_id,
+ cc_value,
+ cc_channel);
+}
+
+void nrfx_timer_extended_compare(nrfx_timer_t const * const p_instance,
+ nrf_timer_cc_channel_t cc_channel,
+ uint32_t cc_value,
+ nrf_timer_short_mask_t timer_short_mask,
+ bool enable_int)
+{
+ nrf_timer_shorts_disable(p_instance->p_reg,
+ (TIMER_SHORTS_COMPARE0_STOP_Msk << cc_channel) |
+ (TIMER_SHORTS_COMPARE0_CLEAR_Msk << cc_channel));
+
+ nrf_timer_shorts_enable(p_instance->p_reg, timer_short_mask);
+
+ nrfx_timer_compare(p_instance,
+ cc_channel,
+ cc_value,
+ enable_int);
+ NRFX_LOG_INFO("Timer id: %d, capture value set: %lu, channel: %d.",
+ p_instance->instance_id,
+ cc_value,
+ cc_channel);
+}
+
+void nrfx_timer_compare_int_enable(nrfx_timer_t const * const p_instance,
+ uint32_t channel)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(channel < p_instance->cc_channel_count);
+
+ nrf_timer_event_clear(p_instance->p_reg,
+ nrf_timer_compare_event_get(channel));
+ nrf_timer_int_enable(p_instance->p_reg,
+ nrf_timer_compare_int_get(channel));
+}
+
+void nrfx_timer_compare_int_disable(nrfx_timer_t const * const p_instance,
+ uint32_t channel)
+{
+ NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
+ NRFX_ASSERT(channel < p_instance->cc_channel_count);
+
+ nrf_timer_int_disable(p_instance->p_reg,
+ nrf_timer_compare_int_get(channel));
+}
+
+static void irq_handler(NRF_TIMER_Type * p_reg,
+ timer_control_block_t * p_cb,
+ uint8_t channel_count)
+{
+ uint8_t i;
+ for (i = 0; i < channel_count; ++i)
+ {
+ nrf_timer_event_t event = nrf_timer_compare_event_get(i);
+ nrf_timer_int_mask_t int_mask = nrf_timer_compare_int_get(i);
+
+ if (nrf_timer_event_check(p_reg, event) &&
+ nrf_timer_int_enable_check(p_reg, int_mask))
+ {
+ nrf_timer_event_clear(p_reg, event);
+ NRFX_LOG_DEBUG("Compare event, channel: %d.", i);
+ p_cb->handler(event, p_cb->context);
+ }
+ }
+}
+
+#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
+void nrfx_timer_0_irq_handler(void)
+{
+ irq_handler(NRF_TIMER0, &m_cb[NRFX_TIMER0_INST_IDX],
+ NRF_TIMER_CC_CHANNEL_COUNT(0));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
+void nrfx_timer_1_irq_handler(void)
+{
+ irq_handler(NRF_TIMER1, &m_cb[NRFX_TIMER1_INST_IDX],
+ NRF_TIMER_CC_CHANNEL_COUNT(1));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TIMER2_ENABLED)
+void nrfx_timer_2_irq_handler(void)
+{
+ irq_handler(NRF_TIMER2, &m_cb[NRFX_TIMER2_INST_IDX],
+ NRF_TIMER_CC_CHANNEL_COUNT(2));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TIMER3_ENABLED)
+void nrfx_timer_3_irq_handler(void)
+{
+ irq_handler(NRF_TIMER3, &m_cb[NRFX_TIMER3_INST_IDX],
+ NRF_TIMER_CC_CHANNEL_COUNT(3));
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TIMER4_ENABLED)
+void nrfx_timer_4_irq_handler(void)
+{
+ irq_handler(NRF_TIMER4, &m_cb[NRFX_TIMER4_INST_IDX],
+ NRF_TIMER_CC_CHANNEL_COUNT(4));
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_TIMER_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twi.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twi.c
new file mode 100644
index 0000000..c7492bd
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twi.c
@@ -0,0 +1,723 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_TWI_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_TWI0_ENABLED) || NRFX_CHECK(NRFX_TWI1_ENABLED))
+#error "No enabled TWI instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_twi.h>
+#include <hal/nrf_gpio.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE TWI
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRFX_TWI_EVT_DONE ? "EVT_DONE" : \
+ (event == NRFX_TWI_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
+ (event == NRFX_TWI_EVT_DATA_NACK ? "EVT_DATA_NACK" : \
+ "UNKNOWN ERROR")))
+
+#define EVT_TO_STR_TWI(event) \
+ (event == NRF_TWI_EVENT_STOPPED ? "NRF_TWI_EVENT_STOPPED" : \
+ (event == NRF_TWI_EVENT_RXDREADY ? "NRF_TWI_EVENT_RXDREADY" : \
+ (event == NRF_TWI_EVENT_TXDSENT ? "NRF_TWI_EVENT_TXDSENT" : \
+ (event == NRF_TWI_EVENT_ERROR ? "NRF_TWI_EVENT_ERROR" : \
+ (event == NRF_TWI_EVENT_BB ? "NRF_TWI_EVENT_BB" : \
+ (event == NRF_TWI_EVENT_SUSPENDED ? "NRF_TWI_EVENT_SUSPENDED" : \
+ "UNKNOWN ERROR"))))))
+
+#define TRANSFER_TO_STR(type) \
+ (type == NRFX_TWI_XFER_TX ? "XFER_TX" : \
+ (type == NRFX_TWI_XFER_RX ? "XFER_RX" : \
+ (type == NRFX_TWI_XFER_TXRX ? "XFER_TXRX" : \
+ (type == NRFX_TWI_XFER_TXTX ? "XFER_TXTX" : \
+ "UNKNOWN TRANSFER TYPE"))))
+
+#define TWI_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
+ NRF_GPIO_PIN_DIR_INPUT, \
+ NRF_GPIO_PIN_INPUT_CONNECT, \
+ NRF_GPIO_PIN_PULLUP, \
+ NRF_GPIO_PIN_S0D1, \
+ NRF_GPIO_PIN_NOSENSE)
+
+#define HW_TIMEOUT 10000
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_twi_evt_handler_t handler;
+ void * p_context;
+ volatile uint32_t int_mask;
+ nrfx_twi_xfer_desc_t xfer_desc;
+ uint32_t flags;
+ uint8_t * p_curr_buf;
+ uint8_t curr_length;
+ bool curr_no_stop;
+ nrfx_drv_state_t state;
+ bool error;
+ volatile bool busy;
+ bool repeated;
+ uint8_t bytes_transferred;
+ bool hold_bus_uninit;
+} twi_control_block_t;
+
+static twi_control_block_t m_cb[NRFX_TWI_ENABLED_COUNT];
+
+static nrfx_err_t twi_process_error(uint32_t errorsrc)
+{
+ nrfx_err_t ret = NRFX_ERROR_INTERNAL;
+
+ if (errorsrc & NRF_TWI_ERROR_OVERRUN)
+ {
+ ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
+ }
+
+ if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
+ {
+ ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
+ }
+
+ if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
+ {
+ ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
+ }
+
+ return ret;
+}
+
+
+
+nrfx_err_t nrfx_twi_init(nrfx_twi_t const * p_instance,
+ nrfx_twi_config_t const * p_config,
+ nrfx_twi_evt_handler_t event_handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(p_config->scl != p_config->sda);
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_TWI_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_TWI0_ENABLED)
+ nrfx_twi_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_TWI1_ENABLED)
+ nrfx_twi_1_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_twi,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ p_cb->handler = event_handler;
+ p_cb->p_context = p_context;
+ p_cb->int_mask = 0;
+ p_cb->repeated = false;
+ p_cb->busy = false;
+ p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
+
+ /* To secure correct signal levels on the pins used by the TWI
+ master when the system is in OFF mode, and when the TWI master is
+ disabled, these pins must be configured in the GPIO peripheral.
+ */
+ TWI_PIN_INIT(p_config->scl);
+ TWI_PIN_INIT(p_config->sda);
+
+ NRF_TWI_Type * p_twi = p_instance->p_twi;
+ nrf_twi_pins_set(p_twi, p_config->scl, p_config->sda);
+ nrf_twi_frequency_set(p_twi,
+ (nrf_twi_frequency_t)p_config->frequency);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twi),
+ p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twi));
+ }
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_twi_uninit(nrfx_twi_t const * p_instance)
+{
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twi));
+ }
+ nrfx_twi_disable(p_instance);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_twi);
+#endif
+
+ if (!p_cb->hold_bus_uninit)
+ {
+ nrf_gpio_cfg_default(p_instance->p_twi->PSELSCL);
+ nrf_gpio_cfg_default(p_instance->p_twi->PSELSDA);
+ }
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
+}
+
+void nrfx_twi_enable(nrfx_twi_t const * p_instance)
+{
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
+
+ NRF_TWI_Type * p_twi = p_instance->p_twi;
+ nrf_twi_enable(p_twi);
+
+ p_cb->state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
+}
+
+void nrfx_twi_disable(nrfx_twi_t const * p_instance)
+{
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ NRF_TWI_Type * p_twi = p_instance->p_twi;
+ nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
+ nrf_twi_shorts_disable(p_twi, NRF_TWI_ALL_SHORTS_MASK);
+ nrf_twi_disable(p_twi);
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
+}
+
+static bool twi_send_byte(NRF_TWI_Type * p_twi,
+ uint8_t const * p_data,
+ uint8_t length,
+ uint8_t * p_bytes_transferred,
+ bool no_stop)
+{
+ if (*p_bytes_transferred < length)
+ {
+ nrf_twi_txd_set(p_twi, p_data[*p_bytes_transferred]);
+ ++(*p_bytes_transferred);
+ }
+ else
+ {
+ if (no_stop)
+ {
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
+ return false;
+ }
+ else
+ {
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+ }
+ }
+ return true;
+}
+
+static void twi_receive_byte(NRF_TWI_Type * p_twi,
+ uint8_t * p_data,
+ uint8_t length,
+ uint8_t * p_bytes_transferred)
+{
+ if (*p_bytes_transferred < length)
+ {
+ p_data[*p_bytes_transferred] = nrf_twi_rxd_get(p_twi);
+
+ ++(*p_bytes_transferred);
+
+ if (*p_bytes_transferred == length - 1)
+ {
+ nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
+ }
+ else if (*p_bytes_transferred == length)
+ {
+ return;
+ }
+
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+ }
+}
+
+static bool twi_transfer(NRF_TWI_Type * p_twi,
+ bool * p_error,
+ uint8_t * p_bytes_transferred,
+ uint8_t * p_data,
+ uint8_t length,
+ bool no_stop)
+{
+ bool do_stop_check = ((*p_error) || ((*p_bytes_transferred) == length));
+
+ if (*p_error)
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+ }
+ else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+ *p_error = true;
+ }
+ else
+ {
+ if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_TXDSENT))
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_TXDSENT));
+ if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+ *p_error = true;
+ }
+ else
+ {
+ if (!twi_send_byte(p_twi, p_data, length, p_bytes_transferred, no_stop))
+ {
+ return false;
+ }
+ }
+ }
+ else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_RXDREADY))
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_RXDREADY));
+ if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+ {
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+ *p_error = true;
+ }
+ else
+ {
+ twi_receive_byte(p_twi, p_data, length, p_bytes_transferred);
+ }
+ }
+ }
+
+ if (do_stop_check && nrf_twi_event_check(p_twi, NRF_TWI_EVENT_STOPPED))
+ {
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+ NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_STOPPED));
+ return false;
+ }
+
+ return true;
+}
+
+static nrfx_err_t twi_tx_start_transfer(twi_control_block_t * p_cb,
+ NRF_TWI_Type * p_twi,
+ uint8_t const * p_data,
+ uint8_t length,
+ bool no_stop)
+{
+ nrfx_err_t ret_code = NRFX_SUCCESS;
+ volatile int32_t hw_timeout;
+
+ hw_timeout = HW_TIMEOUT;
+
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+ nrf_twi_shorts_set(p_twi, 0);
+
+ p_cb->bytes_transferred = 0;
+ p_cb->error = false;
+
+ // In case TWI is suspended resume its operation.
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX);
+
+ (void)twi_send_byte(p_twi, p_data, length, &p_cb->bytes_transferred, no_stop);
+
+ if (p_cb->handler)
+ {
+ p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
+ NRF_TWI_INT_ERROR_MASK |
+ NRF_TWI_INT_TXDSENT_MASK |
+ NRF_TWI_INT_RXDREADY_MASK;
+ nrf_twi_int_enable(p_twi, p_cb->int_mask);
+ }
+ else
+ {
+ while ((hw_timeout > 0) &&
+ twi_transfer(p_twi,
+ &p_cb->error,
+ &p_cb->bytes_transferred,
+ (uint8_t *)p_data,
+ length,
+ no_stop))
+ {
+ hw_timeout--;
+ }
+
+ if (p_cb->error)
+ {
+ uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
+
+ if (errorsrc)
+ {
+ ret_code = twi_process_error(errorsrc);
+ }
+ }
+
+ if (hw_timeout <= 0)
+ {
+ nrf_twi_disable(p_twi);
+ nrf_twi_enable(p_twi);
+ ret_code = NRFX_ERROR_INTERNAL;
+ }
+
+ }
+ return ret_code;
+}
+
+static nrfx_err_t twi_rx_start_transfer(twi_control_block_t * p_cb,
+ NRF_TWI_Type * p_twi,
+ uint8_t const * p_data,
+ uint8_t length)
+{
+ nrfx_err_t ret_code = NRFX_SUCCESS;
+ volatile int32_t hw_timeout;
+
+ hw_timeout = HW_TIMEOUT;
+
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+ nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+
+ p_cb->bytes_transferred = 0;
+ p_cb->error = false;
+
+ if (length == 1)
+ {
+ nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
+ }
+ else
+ {
+ nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
+ }
+ // In case TWI is suspended resume its operation.
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+ nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);
+
+ if (p_cb->handler)
+ {
+ p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
+ NRF_TWI_INT_ERROR_MASK |
+ NRF_TWI_INT_TXDSENT_MASK |
+ NRF_TWI_INT_RXDREADY_MASK;
+ nrf_twi_int_enable(p_twi, p_cb->int_mask);
+ }
+ else
+ {
+ while ((hw_timeout > 0) &&
+ twi_transfer(p_twi,
+ &p_cb->error,
+ &p_cb->bytes_transferred,
+ (uint8_t*)p_data,
+ length,
+ false))
+ {
+ hw_timeout--;
+ }
+
+ if (p_cb->error)
+ {
+ uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
+
+ if (errorsrc)
+ {
+ ret_code = twi_process_error(errorsrc);
+ }
+ }
+ if (hw_timeout <= 0)
+ {
+ nrf_twi_disable(p_twi);
+ nrf_twi_enable(p_twi);
+ ret_code = NRFX_ERROR_INTERNAL;
+ }
+ }
+ return ret_code;
+}
+
+__STATIC_INLINE nrfx_err_t twi_xfer(twi_control_block_t * p_cb,
+ NRF_TWI_Type * p_twi,
+ nrfx_twi_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
+ nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
+
+ if (p_cb->busy)
+ {
+ nrf_twi_int_enable(p_twi, p_cb->int_mask);
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ p_cb->busy = (NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ? false : true;
+ }
+
+ p_cb->flags = flags;
+ p_cb->xfer_desc = *p_xfer_desc;
+ p_cb->curr_length = p_xfer_desc->primary_length;
+ p_cb->p_curr_buf = p_xfer_desc->p_primary_buf;
+ nrf_twi_address_set(p_twi, p_xfer_desc->address);
+
+ if (p_xfer_desc->type != NRFX_TWI_XFER_RX)
+ {
+ p_cb->curr_no_stop = ((p_xfer_desc->type == NRFX_TWI_XFER_TX) &&
+ !(flags & NRFX_TWI_FLAG_TX_NO_STOP)) ? false : true;
+
+ err_code = twi_tx_start_transfer(p_cb,
+ p_twi,
+ p_xfer_desc->p_primary_buf,
+ p_xfer_desc->primary_length,
+ p_cb->curr_no_stop);
+ }
+ else
+ {
+ p_cb->curr_no_stop = false;
+
+ err_code = twi_rx_start_transfer(p_cb,
+ p_twi,
+ p_xfer_desc->p_primary_buf,
+ p_xfer_desc->primary_length);
+ }
+ if (p_cb->handler == NULL)
+ {
+ p_cb->busy = false;
+ }
+ return err_code;
+}
+
+bool nrfx_twi_is_busy(nrfx_twi_t const * p_instance)
+{
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return p_cb->busy;
+}
+
+nrfx_err_t nrfx_twi_xfer(nrfx_twi_t const * p_instance,
+ nrfx_twi_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ // TXRX and TXTX transfers are supported only in non-blocking mode.
+ NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXRX)));
+ NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXTX)));
+
+ NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
+ NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
+ p_xfer_desc->primary_length,
+ p_xfer_desc->secondary_length);
+ NRFX_LOG_DEBUG("Primary buffer data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
+ p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
+ NRFX_LOG_DEBUG("Secondary buffer data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
+ p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
+
+ err_code = twi_xfer(p_cb, (NRF_TWI_Type *)p_instance->p_twi, p_xfer_desc, flags);
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_twi_tx(nrfx_twi_t const * p_instance,
+ uint8_t address,
+ uint8_t const * p_data,
+ size_t length,
+ bool no_stop)
+{
+ nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length);
+
+ return nrfx_twi_xfer(p_instance, &xfer, no_stop ? NRFX_TWI_FLAG_TX_NO_STOP : 0);
+}
+
+nrfx_err_t nrfx_twi_rx(nrfx_twi_t const * p_instance,
+ uint8_t address,
+ uint8_t * p_data,
+ size_t length)
+{
+ nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_RX(address, p_data, length);
+ return nrfx_twi_xfer(p_instance, &xfer, 0);
+}
+
+size_t nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance)
+{
+ return m_cb[p_instance->drv_inst_idx].bytes_transferred;
+}
+
+uint32_t nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance)
+{
+ return (uint32_t)nrf_twi_event_address_get(p_instance->p_twi, NRF_TWI_EVENT_STOPPED);
+}
+
+static void twi_irq_handler(NRF_TWI_Type * p_twi, twi_control_block_t * p_cb)
+{
+ NRFX_ASSERT(p_cb->handler);
+
+ if (twi_transfer(p_twi,
+ &p_cb->error,
+ &p_cb->bytes_transferred,
+ p_cb->p_curr_buf,
+ p_cb->curr_length,
+ p_cb->curr_no_stop ))
+ {
+ return;
+ }
+
+ if (!p_cb->error &&
+ ((p_cb->xfer_desc.type == NRFX_TWI_XFER_TXRX) ||
+ (p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)) &&
+ p_cb->p_curr_buf == p_cb->xfer_desc.p_primary_buf)
+ {
+ p_cb->p_curr_buf = p_cb->xfer_desc.p_secondary_buf;
+ p_cb->curr_length = p_cb->xfer_desc.secondary_length;
+ p_cb->curr_no_stop = (p_cb->flags & NRFX_TWI_FLAG_TX_NO_STOP);
+
+ if (p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)
+ {
+ (void)twi_tx_start_transfer(p_cb,
+ p_twi,
+ p_cb->p_curr_buf,
+ p_cb->curr_length,
+ p_cb->curr_no_stop);
+ }
+ else
+ {
+ (void)twi_rx_start_transfer(p_cb, p_twi, p_cb->p_curr_buf, p_cb->curr_length);
+ }
+ }
+ else
+ {
+ nrfx_twi_evt_t event;
+ event.xfer_desc = p_cb->xfer_desc;
+
+ if (p_cb->error)
+ {
+ uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
+ if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
+ {
+ event.type = NRFX_TWI_EVT_ADDRESS_NACK;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_ADDRESS_NACK));
+ }
+ else if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
+ {
+ event.type = NRFX_TWI_EVT_DATA_NACK;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DATA_NACK));
+ }
+ }
+ else
+ {
+ event.type = NRFX_TWI_EVT_DONE;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DONE));
+ }
+
+ p_cb->busy = false;
+
+ if (!(NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER & p_cb->flags))
+ {
+ p_cb->handler(&event, p_cb->p_context);
+ }
+ }
+
+}
+
+#if NRFX_CHECK(NRFX_TWI0_ENABLED)
+void nrfx_twi_0_irq_handler(void)
+{
+ twi_irq_handler(NRF_TWI0, &m_cb[NRFX_TWI0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TWI1_ENABLED)
+void nrfx_twi_1_irq_handler(void)
+{
+ twi_irq_handler(NRF_TWI1, &m_cb[NRFX_TWI1_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_TWI_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twim.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twim.c
new file mode 100644
index 0000000..7d9cb36
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twim.c
@@ -0,0 +1,664 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_TWIM_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_TWIM0_ENABLED) || NRFX_CHECK(NRFX_TWIM1_ENABLED))
+#error "No enabled TWIM instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_twim.h>
+#include <hal/nrf_gpio.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE TWIM
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRFX_TWIM_EVT_DONE ? "EVT_DONE" : \
+ (event == NRFX_TWIM_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
+ (event == NRFX_TWIM_EVT_DATA_NACK ? "EVT_DATA_NACK" : \
+ "UNKNOWN ERROR")))
+
+#define EVT_TO_STR_TWIM(event) \
+ (event == NRF_TWIM_EVENT_STOPPED ? "NRF_TWIM_EVENT_STOPPED" : \
+ (event == NRF_TWIM_EVENT_ERROR ? "NRF_TWIM_EVENT_ERROR" : \
+ (event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \
+ (event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \
+ (event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \
+ (event == NRF_TWIM_EVENT_LASTRX ? "NRF_TWIM_EVENT_LASTRX" : \
+ (event == NRF_TWIM_EVENT_LASTTX ? "NRF_TWIM_EVENT_LASTTX" : \
+ "UNKNOWN ERROR")))))))
+
+#define TRANSFER_TO_STR(type) \
+ (type == NRFX_TWIM_XFER_TX ? "XFER_TX" : \
+ (type == NRFX_TWIM_XFER_RX ? "XFER_RX" : \
+ (type == NRFX_TWIM_XFER_TXRX ? "XFER_TXRX" : \
+ (type == NRFX_TWIM_XFER_TXTX ? "XFER_TXTX" : \
+ "UNKNOWN TRANSFER TYPE"))))
+
+#define TWIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
+ NRF_GPIO_PIN_DIR_INPUT, \
+ NRF_GPIO_PIN_INPUT_CONNECT, \
+ NRF_GPIO_PIN_PULLUP, \
+ NRF_GPIO_PIN_S0D1, \
+ NRF_GPIO_PIN_NOSENSE)
+
+#define TWIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
+ (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+ NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
+
+#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
+#define TWIM0_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM0, __VA_ARGS__)
+#else
+#define TWIM0_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
+#define TWIM1_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM1, __VA_ARGS__)
+#else
+#define TWIM1_LENGTH_VALIDATE(...) 0
+#endif
+
+#define TWIM_LENGTH_VALIDATE(drv_inst_idx, len1, len2) \
+ (TWIM0_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
+ TWIM1_LENGTH_VALIDATE(drv_inst_idx, len1, len2))
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_twim_evt_handler_t handler;
+ void * p_context;
+ volatile uint32_t int_mask;
+ nrfx_twim_xfer_desc_t xfer_desc;
+ uint32_t flags;
+ uint8_t * p_curr_buf;
+ size_t curr_length;
+ bool curr_no_stop;
+ nrfx_drv_state_t state;
+ bool error;
+ volatile bool busy;
+ bool repeated;
+ uint8_t bytes_transferred;
+ bool hold_bus_uninit;
+#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ nrf_twim_frequency_t bus_frequency;
+#endif
+} twim_control_block_t;
+
+static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT];
+
+static nrfx_err_t twi_process_error(uint32_t errorsrc)
+{
+ nrfx_err_t ret = NRFX_ERROR_INTERNAL;
+
+ if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
+ {
+ ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
+ }
+
+ if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
+ {
+ ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
+ }
+
+ return ret;
+}
+
+nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
+ nrfx_twim_config_t const * p_config,
+ nrfx_twim_evt_handler_t event_handler,
+ void * p_context)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(p_config->scl != p_config->sda);
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
+ nrfx_twim_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
+ nrfx_twim_1_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_twim,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ p_cb->handler = event_handler;
+ p_cb->p_context = p_context;
+ p_cb->int_mask = 0;
+ p_cb->repeated = false;
+ p_cb->busy = false;
+ p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
+#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ p_cb->bus_frequency = (nrf_twim_frequency_t)p_config->frequency;
+#endif
+
+ /* To secure correct signal levels on the pins used by the TWI
+ master when the system is in OFF mode, and when the TWI master is
+ disabled, these pins must be configured in the GPIO peripheral.
+ */
+ TWIM_PIN_INIT(p_config->scl);
+ TWIM_PIN_INIT(p_config->sda);
+
+ NRF_TWIM_Type * p_twim = p_instance->p_twim;
+ nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
+ nrf_twim_frequency_set(p_twim,
+ (nrf_twim_frequency_t)p_config->frequency);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twim),
+ p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twim));
+ }
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
+{
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ if (p_cb->handler)
+ {
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twim));
+ }
+ nrfx_twim_disable(p_instance);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_twim);
+#endif
+
+ if (!p_cb->hold_bus_uninit)
+ {
+ nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SCL);
+ nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SDA);
+ }
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+ NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
+}
+
+void nrfx_twim_enable(nrfx_twim_t const * p_instance)
+{
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
+
+ nrf_twim_enable(p_instance->p_twim);
+
+ p_cb->state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
+}
+
+void nrfx_twim_disable(nrfx_twim_t const * p_instance)
+{
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ NRF_TWIM_Type * p_twim = p_instance->p_twim;
+ p_cb->int_mask = 0;
+ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
+ nrf_twim_shorts_disable(p_twim, NRF_TWIM_ALL_SHORTS_MASK);
+ nrf_twim_disable(p_twim);
+
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
+}
+
+
+bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance)
+{
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return p_cb->busy;
+}
+
+
+__STATIC_INLINE void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
+{
+ if (NRFX_TWIM_FLAG_TX_POSTINC & flags)
+ {
+ nrf_twim_tx_list_enable(p_twim);
+ }
+ else
+ {
+ nrf_twim_tx_list_disable(p_twim);
+ }
+
+ if (NRFX_TWIM_FLAG_RX_POSTINC & flags)
+ {
+ nrf_twim_rx_list_enable(p_twim);
+ }
+ else
+ {
+ nrf_twim_rx_list_disable(p_twim);
+ }
+}
+__STATIC_INLINE nrfx_err_t twim_xfer(twim_control_block_t * p_cb,
+ NRF_TWIM_Type * p_twim,
+ nrfx_twim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX;
+ nrf_twim_event_t evt_to_wait = NRF_TWIM_EVENT_STOPPED;
+
+ if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
+ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
+ if (p_cb->busy)
+ {
+ nrf_twim_int_enable(p_twim, p_cb->int_mask);
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ else
+ {
+ p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) ||
+ (NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true;
+ }
+
+ p_cb->xfer_desc = *p_xfer_desc;
+ p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false;
+ nrf_twim_address_set(p_twim, p_xfer_desc->address);
+
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+
+ twim_list_enable_handle(p_twim, flags);
+ switch (p_xfer_desc->type)
+ {
+ case NRFX_TWIM_XFER_TXTX:
+ NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER));
+ NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER));
+ NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER));
+ if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
+ nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
+ while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
+ {}
+ NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED));
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+ nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
+ p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ break;
+ case NRFX_TWIM_XFER_TXRX:
+ nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+ if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
+ NRF_TWIM_SHORT_LASTRX_STOP_MASK);
+ p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ break;
+ case NRFX_TWIM_XFER_TX:
+ nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+ if (NRFX_TWIM_FLAG_TX_NO_STOP & flags)
+ {
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
+ p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+ evt_to_wait = NRF_TWIM_EVENT_SUSPENDED;
+ }
+ else
+ {
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
+ p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ }
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ break;
+ case NRFX_TWIM_XFER_RX:
+ nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
+ p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ start_task = NRF_TWIM_TASK_STARTRX;
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ break;
+ default:
+ err_code = NRFX_ERROR_INVALID_PARAM;
+ break;
+ }
+
+ if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX))
+ {
+ nrf_twim_task_trigger(p_twim, start_task);
+ }
+
+ if (p_cb->handler)
+ {
+ if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)
+ {
+ p_cb->int_mask = NRF_TWIM_INT_ERROR_MASK;
+ }
+ nrf_twim_int_enable(p_twim, p_cb->int_mask);
+
+#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && ((p_xfer_desc->type == NRFX_TWIM_XFER_TX) ||
+ (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)))
+ {
+ p_cb->flags = flags;
+ twim_list_enable_handle(p_twim, 0);
+ p_twim->FREQUENCY = 0;
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+ nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
+ }
+#endif
+ }
+ else
+ {
+ while (!nrf_twim_event_check(p_twim, evt_to_wait))
+ {
+ if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
+ {
+ NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
+ evt_to_wait = NRF_TWIM_EVENT_STOPPED;
+ }
+ }
+
+ uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
+
+ p_cb->busy = false;
+
+ if (errorsrc)
+ {
+ err_code = twi_process_error(errorsrc);
+ }
+ }
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
+ nrfx_twim_xfer_desc_t const * p_xfer_desc,
+ uint32_t flags)
+{
+ NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
+ p_xfer_desc->primary_length,
+ p_xfer_desc->secondary_length));
+
+ nrfx_err_t err_code = NRFX_SUCCESS;
+ twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ // TXRX and TXTX transfers are supported only in non-blocking mode.
+ NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
+ NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));
+
+ NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
+ NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
+ p_xfer_desc->primary_length,
+ p_xfer_desc->secondary_length);
+ NRFX_LOG_DEBUG("Primary buffer data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
+ p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
+ NRFX_LOG_DEBUG("Secondary buffer data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
+ p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
+
+ err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+nrfx_err_t nrfx_twim_tx(nrfx_twim_t const * p_instance,
+ uint8_t address,
+ uint8_t const * p_data,
+ size_t length,
+ bool no_stop)
+{
+ nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_TX(address, (uint8_t*)p_data, length);
+
+ return nrfx_twim_xfer(p_instance, &xfer, no_stop ? NRFX_TWIM_FLAG_TX_NO_STOP : 0);
+}
+
+nrfx_err_t nrfx_twim_rx(nrfx_twim_t const * p_instance,
+ uint8_t address,
+ uint8_t * p_data,
+ size_t length)
+{
+ nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_RX(address, p_data, length);
+ return nrfx_twim_xfer(p_instance, &xfer, 0);
+}
+
+uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,
+ nrfx_twim_xfer_type_t xfer_type)
+{
+ return (uint32_t)nrf_twim_task_address_get(p_instance->p_twim,
+ (xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
+}
+
+uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)
+{
+ return (uint32_t)nrf_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED);
+}
+
+static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
+{
+
+#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+ /* Handle only workaround case. Can be used without TWIM handler in IRQs. */
+ if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
+ {
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+ nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
+ if (p_twim->FREQUENCY == 0)
+ {
+ // Set enable to zero to reset TWIM internal state.
+ nrf_twim_disable(p_twim);
+ nrf_twim_enable(p_twim);
+
+ // Set proper frequency.
+ nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
+ twim_list_enable_handle(p_twim, p_cb->flags);
+
+ // Start proper transmission.
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
+ return;
+ }
+ }
+#endif
+
+ NRFX_ASSERT(p_cb->handler);
+
+ if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
+ {
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+ NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
+ if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
+ {
+ nrf_twim_int_disable(p_twim, p_cb->int_mask);
+ p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
+ nrf_twim_int_enable(p_twim, p_cb->int_mask);
+
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
+ return;
+ }
+ }
+
+ nrfx_twim_evt_t event;
+
+ if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
+ {
+ NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
+ event.xfer_desc = p_cb->xfer_desc;
+ if (p_cb->error)
+ {
+
+ event.xfer_desc.primary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_RX) ?
+ nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);
+ event.xfer_desc.secondary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TXRX) ?
+ nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);
+
+ }
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
+ if (!p_cb->repeated || p_cb->error)
+ {
+ nrf_twim_shorts_set(p_twim, 0);
+ p_cb->int_mask = 0;
+ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
+ }
+ }
+ else
+ {
+ nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+ NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
+ if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
+ {
+ event.xfer_desc = p_cb->xfer_desc;
+ if (!p_cb->repeated)
+ {
+ nrf_twim_shorts_set(p_twim, 0);
+ p_cb->int_mask = 0;
+ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
+ }
+ }
+ else
+ {
+ nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
+ p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
+ nrf_twim_int_enable(p_twim, p_cb->int_mask);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
+ nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+ return;
+ }
+ }
+
+ uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
+ if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
+ {
+ event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
+ }
+ else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
+ {
+ event.type = NRFX_TWIM_EVT_DATA_NACK;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
+ }
+ else
+ {
+ event.type = NRFX_TWIM_EVT_DONE;
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
+ }
+
+ if (!p_cb->repeated)
+ {
+ p_cb->busy = false;
+ }
+ p_cb->handler(&event, p_cb->p_context);
+}
+
+#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
+void nrfx_twim_0_irq_handler(void)
+{
+ twim_irq_handler(NRF_TWIM0, &m_cb[NRFX_TWIM0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
+void nrfx_twim_1_irq_handler(void)
+{
+ twim_irq_handler(NRF_TWIM1, &m_cb[NRFX_TWIM1_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_TWIM_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twis.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twis.c
new file mode 100644
index 0000000..9fb7a49
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_twis.c
@@ -0,0 +1,834 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_TWIS_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_TWIS0_ENABLED) || NRFX_CHECK(NRFX_TWIS1_ENABLED))
+#error "No enabled TWIS instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_twis.h>
+#include "prs/nrfx_prs.h"
+
+#define NRFX_LOG_MODULE TWIS
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \
+ (event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \
+ (event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \
+ (event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \
+ (event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \
+ (event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : \
+ "UNKNOWN EVENT"))))))
+
+
+/**
+ * @brief Actual state of internal state machine
+ *
+ * Current substate of powered on state.
+ */
+typedef enum
+{
+ NRFX_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission
+ NRFX_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data
+ NRFX_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending)
+ NRFX_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer
+ NRFX_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving)
+} nrfx_twis_substate_t;
+
+// Control block - driver instance local data.
+typedef struct
+{
+ nrfx_twis_event_handler_t ev_handler;
+ // Internal copy of hardware errors flags merged with specific internal
+ // driver errors flags.
+ // This value can be changed in the interrupt and cleared in the main program.
+ // Always use Atomic load-store when updating this value in main loop.
+ volatile uint32_t error;
+ nrfx_drv_state_t state;
+ volatile nrfx_twis_substate_t substate;
+
+ volatile bool semaphore;
+} twis_control_block_t;
+static twis_control_block_t m_cb[NRFX_TWIS_ENABLED_COUNT];
+
+/**
+ * @brief Used interrupts mask
+ *
+ * Mask for all interrupts used by this library
+ */
+static const uint32_t m_used_ints_mask = NRF_TWIS_INT_STOPPED_MASK |
+ NRF_TWIS_INT_ERROR_MASK |
+ NRF_TWIS_INT_RXSTARTED_MASK |
+ NRF_TWIS_INT_TXSTARTED_MASK |
+ NRF_TWIS_INT_WRITE_MASK |
+ NRF_TWIS_INT_READ_MASK;
+
+/**
+ * @brief Clear all events
+ *
+ * Function clears all actually pending events
+ */
+static void nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)
+{
+ /* Clear all events */
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED);
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR);
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED);
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED);
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE);
+ nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ);
+}
+
+/**
+ * @brief Reset all the registers to known state
+ *
+ * This function clears all registers that requires it to known state.
+ * TWIS is left disabled after this function.
+ * All events are cleared.
+ * @param[out] p_reg TWIS to reset register address
+ */
+static inline void nrfx_twis_swreset(NRF_TWIS_Type * p_reg)
+{
+ /* Disable TWIS */
+ nrf_twis_disable(p_reg);
+
+ /* Disconnect pins */
+ nrf_twis_pins_set(p_reg, ~0U, ~0U);
+
+ /* Disable interrupt global for the instance */
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
+
+ /* Disable interrupts */
+ nrf_twis_int_disable(p_reg, ~0U);
+}
+
+/**
+ * @brief Configure pin
+ *
+ * Function configures selected for work as SDA or SCL.
+ * @param pin Pin number to configure
+ */
+static inline void nrfx_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull)
+{
+ nrf_gpio_cfg(pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ NRF_GPIO_PIN_INPUT_DISCONNECT,
+ pull,
+ NRF_GPIO_PIN_S0D1,
+ NRF_GPIO_PIN_NOSENSE);
+}
+
+/**
+ * @brief Auxiliary function for getting event state on right bit possition
+ *
+ * This function calls @ref nrf_twis_event_get function but the the result
+ * is shifted to match INTEN register scheme.
+ *
+ * @param[in,out] p_reg TWIS to read event from
+ * @param ev Event code
+ *
+ * @return Selected event state shifted by @ref nrfx_event_to_bitpos
+ *
+ * @sa nrf_twis_event_get
+ * @sa nrfx_event_to_bitpos
+ */
+static inline uint32_t nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg,
+ nrf_twis_event_t ev)
+{
+ return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrfx_event_to_bitpos(ev);
+}
+
+/**
+ * @brief Auxiliary function for checking event bit inside given flags value
+ *
+ * Function used here to check presence of the event inside given flags value.
+ * It transforms given event to bit possition and then checks if in given variable it is cleared.
+ *
+ * @param flags Flags to test
+ * @param ev Event code
+ *
+ * @retval true Flag for selected event is set
+ * @retval false Flag for selected event is cleared
+ */
+static inline bool nrfx_twis_check_bit(uint32_t flags,
+ nrf_twis_event_t ev)
+{
+ return 0 != (flags & (1U << nrfx_event_to_bitpos(ev)));
+}
+
+/**
+ * @brief Auxiliary function for clearing event bit in given flags value
+ *
+ * Function used to clear selected event bit.
+ *
+ * @param flags Flags to process
+ * @param ev Event code to clear
+ *
+ * @return Value @em flags with cleared event bit that matches given @em ev
+ */
+static inline uint32_t nrfx_twis_clear_bit(uint32_t flags,
+ nrf_twis_event_t ev)
+{
+ return flags & ~(1U << nrfx_event_to_bitpos(ev));
+}
+
+static void call_event_handler(twis_control_block_t const * p_cb,
+ nrfx_twis_evt_t const * p_evt)
+{
+ nrfx_twis_event_handler_t handler = p_cb->ev_handler;
+ if (handler != NULL)
+ {
+ handler(p_evt);
+ }
+}
+
+/**
+ * @brief Auxiliary function for error processing
+ *
+ * Function called when in current substate the event apears and it cannot be processed.
+ * It should be called also on ERROR event.
+ * If given @em error parameter has zero value the @ref NRFX_TWIS_ERROR_UNEXPECTED_EVENT
+ * would be set.
+ *
+ * @param p_cb Pointer to the driver instance control block.
+ * @param evt What error event raport to event handler
+ * @param error Error flags
+ */
+static inline void nrfx_twis_process_error(twis_control_block_t * p_cb,
+ nrfx_twis_evt_type_t evt,
+ uint32_t error)
+{
+ if (0 == error)
+ {
+ error = NRFX_TWIS_ERROR_UNEXPECTED_EVENT;
+ }
+ nrfx_twis_evt_t evdata;
+ evdata.type = evt;
+ evdata.data.error = error;
+
+ p_cb->error |= error;
+
+ call_event_handler(p_cb, &evdata);
+}
+
+static void nrfx_twis_state_machine(NRF_TWIS_Type * p_reg,
+ twis_control_block_t * p_cb)
+{
+ if (!NRFX_TWIS_NO_SYNC_MODE)
+ {
+ /* Exclude parallel processing of this function */
+ if (p_cb->semaphore)
+ {
+ return;
+ }
+ p_cb->semaphore = 1;
+ }
+
+ /* Event data structure to be passed into event handler */
+ nrfx_twis_evt_t evdata;
+ /* Current substate copy */
+ nrfx_twis_substate_t substate = p_cb->substate;
+ /* Event flags */
+ uint32_t ev = 0;
+
+ /* Get all events */
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED);
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR);
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED);
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED);
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE);
+ ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ);
+
+ /* State machine */
+ while (0 != ev)
+ {
+ switch (substate)
+ {
+ case NRFX_TWIS_SUBSTATE_IDLE:
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
+ {
+ /* Stopped event is always allowed in IDLE state - just ignore */
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
+ }
+ else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ))
+ {
+ evdata.type = NRFX_TWIS_EVT_READ_REQ;
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED))
+ {
+ substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
+ evdata.data.buf_req = false;
+ }
+ else
+ {
+ substate = NRFX_TWIS_SUBSTATE_READ_WAITING;
+ evdata.data.buf_req = true;
+ }
+ call_event_handler(p_cb, &evdata);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
+ }
+ else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE))
+ {
+ evdata.type = NRFX_TWIS_EVT_WRITE_REQ;
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED))
+ {
+ substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
+ evdata.data.buf_req = false;
+ }
+ else
+ {
+ substate = NRFX_TWIS_SUBSTATE_WRITE_WAITING;
+ evdata.data.buf_req = true;
+ }
+ call_event_handler(p_cb, &evdata);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
+ }
+ else
+ {
+ nrfx_twis_process_error(p_cb,
+ NRFX_TWIS_EVT_GENERAL_ERROR,
+ nrf_twis_error_source_get_and_clear(p_reg));
+ ev = 0;
+ }
+ break;
+ case NRFX_TWIS_SUBSTATE_READ_WAITING:
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
+ {
+ substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
+ /* Any other bits requires further processing in PENDING substate */
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
+ }
+ else
+ {
+ nrfx_twis_process_error(p_cb,
+ NRFX_TWIS_EVT_READ_ERROR,
+ nrf_twis_error_source_get_and_clear(p_reg));
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = 0;
+ }
+ break;
+ case NRFX_TWIS_SUBSTATE_READ_PENDING:
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
+ {
+ evdata.type = NRFX_TWIS_EVT_READ_DONE;
+ evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg);
+ NRFX_LOG_INFO("Transfer tx_len:%d", evdata.data.tx_amount);
+ NRFX_LOG_DEBUG("Tx data:");
+ NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)p_reg->TXD.PTR,
+ evdata.data.tx_amount * sizeof(uint8_t));
+ call_event_handler(p_cb, &evdata);
+ /* Go to idle and repeat the state machine if READ or WRITE events detected.
+ * This time READ or WRITE would be started */
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
+ }
+ else
+ {
+ nrfx_twis_process_error(p_cb,
+ NRFX_TWIS_EVT_READ_ERROR,
+ nrf_twis_error_source_get_and_clear(p_reg));
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = 0;
+ }
+ break;
+ case NRFX_TWIS_SUBSTATE_WRITE_WAITING:
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
+ {
+ substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
+ /* Any other bits requires further processing in PENDING substate */
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
+ }
+ else
+ {
+ nrfx_twis_process_error(p_cb,
+ NRFX_TWIS_EVT_WRITE_ERROR,
+ nrf_twis_error_source_get_and_clear(p_reg));
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = 0;
+ }
+ break;
+ case NRFX_TWIS_SUBSTATE_WRITE_PENDING:
+ if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
+ nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
+ {
+ evdata.type = NRFX_TWIS_EVT_WRITE_DONE;
+ evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg);
+ call_event_handler(p_cb, &evdata);
+ /* Go to idle and repeat the state machine if READ or WRITE events detected.
+ * This time READ or WRITE would be started */
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
+ }
+ else
+ {
+ nrfx_twis_process_error(p_cb,
+ NRFX_TWIS_EVT_WRITE_ERROR,
+ nrf_twis_error_source_get_and_clear(p_reg));
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ ev = 0;
+ }
+ break;
+ default:
+ substate = NRFX_TWIS_SUBSTATE_IDLE;
+ /* Do not clear any events and repeat the machine */
+ break;
+ }
+ }
+
+ p_cb->substate = substate;
+ if (!NRFX_TWIS_NO_SYNC_MODE)
+ {
+ p_cb->semaphore = 0;
+ }
+}
+
+
+static inline void nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)
+{
+ if (!NRFX_TWIS_NO_SYNC_MODE)
+ {
+ NRF_TWIS_Type * p_reg = p_instance->p_reg;
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ if (NULL == p_cb->ev_handler)
+ {
+ nrfx_twis_state_machine(p_reg, p_cb);
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ * Implementation of interface functions
+ *
+ */
+
+
+nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
+ nrfx_twis_config_t const * p_config,
+ nrfx_twis_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(p_config->scl != p_config->sda);
+ nrfx_err_t err_code;
+
+ NRF_TWIS_Type * p_reg = p_instance->p_reg;
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_TWIS_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_TWIS0_ENABLED)
+ nrfx_twis_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_TWIS1_ENABLED)
+ nrfx_twis_1_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_reg,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ if (!NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
+ {
+ nrfx_twis_swreset(p_reg);
+ }
+
+ nrfx_twis_config_pin(p_config->scl, p_config->scl_pull);
+ nrfx_twis_config_pin(p_config->sda, p_config->sda_pull);
+
+ nrf_twis_config_addr_mask_t addr_mask = (nrf_twis_config_addr_mask_t)0;
+ if (0 == (p_config->addr[0] | p_config->addr[1]))
+ {
+ addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK;
+ }
+ else
+ {
+ if (0 != p_config->addr[0])
+ {
+ addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK;
+ }
+ if (0 != p_config->addr[1])
+ {
+ addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK;
+ }
+ }
+
+ /* Peripheral interrupt configure
+ * (note - interrupts still needs to be configured in INTEN register.
+ * This is done in enable function) */
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg),
+ p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
+
+ /* Configure */
+ nrf_twis_pins_set (p_reg, p_config->scl, p_config->sda);
+ nrf_twis_address_set (p_reg, 0, p_config->addr[0]);
+ nrf_twis_address_set (p_reg, 1, p_config->addr[1]);
+ nrf_twis_config_address_set(p_reg, addr_mask);
+
+ /* Clear semaphore */
+ if (!NRFX_TWIS_NO_SYNC_MODE)
+ {
+ p_cb->semaphore = 0;
+ }
+ /* Set internal instance variables */
+ p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
+ p_cb->ev_handler = event_handler;
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+void nrfx_twis_uninit(nrfx_twis_t const * p_instance)
+{
+ NRF_TWIS_Type * p_reg = p_instance->p_reg;
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ TWIS_PSEL_Type psel = p_reg->PSEL;
+
+ nrfx_twis_swreset(p_reg);
+
+ /* Clear pins state if */
+ if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL))
+ {
+ nrf_gpio_cfg_default(psel.SCL);
+ }
+ if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA))
+ {
+ nrf_gpio_cfg_default(psel.SDA);
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_reg);
+#endif
+
+ /* Clear variables */
+ p_cb->ev_handler = NULL;
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+
+void nrfx_twis_enable(nrfx_twis_t const * p_instance)
+{
+ NRF_TWIS_Type * p_reg = p_instance->p_reg;
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
+
+ nrfx_twis_clear_all_events(p_reg);
+
+ /* Enable interrupts */
+ if (NULL != p_cb->ev_handler)
+ {
+ nrf_twis_int_enable(p_reg, m_used_ints_mask);
+ }
+
+ nrf_twis_enable(p_reg);
+ p_cb->error = 0;
+ p_cb->state = NRFX_DRV_STATE_POWERED_ON;
+ p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
+}
+
+
+void nrfx_twis_disable(nrfx_twis_t const * p_instance)
+{
+ NRF_TWIS_Type * p_reg = p_instance->p_reg;
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ nrf_twis_int_disable(p_reg, m_used_ints_mask);
+
+ nrf_twis_disable(p_reg);
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+}
+
+/* ARM recommends not using the LDREX and STREX instructions in C code.
+ * This is because the compiler might generate loads and stores between
+ * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
+ * This recommendation also applies to the byte, halfword, and doubleword
+ * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
+ *
+ * This is the reason for the function below to be implemented in assembly.
+ */
+//lint -save -e578
+#if defined (__CC_ARM )
+static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
+{
+ mov r3, r0
+ mov r1, #0
+nrfx_twis_error_get_and_clear_internal_try
+ ldrex r0, [r3]
+ strex r2, r1, [r3]
+ cmp r2, r1 /* did this succeed? */
+ bne nrfx_twis_error_get_and_clear_internal_try /* no - try again */
+ bx lr
+}
+#elif defined ( __GNUC__ )
+static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
+{
+ uint32_t ret;
+ uint32_t temp;
+ __ASM volatile(
+ " .syntax unified \n"
+ "nrfx_twis_error_get_and_clear_internal_try: \n"
+ " ldrex %[ret], [%[perror]] \n"
+ " strex %[temp], %[zero], [%[perror]] \n"
+ " cmp %[temp], %[zero] \n"
+ " bne nrfx_twis_error_get_and_clear_internal_try \n"
+ : /* Output */
+ [ret]"=&l"(ret),
+ [temp]"=&l"(temp)
+ : /* Input */
+ [zero]"l"(0),
+ [perror]"l"(perror)
+ );
+ (void)temp;
+ return ret;
+}
+#elif defined ( __ICCARM__ )
+static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
+{
+ uint32_t ret;
+ uint32_t temp;
+ __ASM volatile(
+ "1: \n"
+ " ldrex %[ret], [%[perror]] \n"
+ " strex %[temp], %[zero], [%[perror]] \n"
+ " cmp %[temp], %[zero] \n"
+ " bne.n 1b \n"
+ : /* Output */
+ [ret]"=&l"(ret),
+ [temp]"=&l"(temp)
+ : /* Input */
+ [zero]"l"(0),
+ [perror]"l"(perror)
+ );
+ (void)temp;
+ return ret;
+}
+#else
+ #error Unknown compiler
+#endif
+//lint -restore
+
+uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ /* Make sure that access to error member is atomic
+ * so there is no bit that is cleared if it is not copied to local variable already. */
+ twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
+}
+
+
+nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
+ void const * p_buf,
+ size_t size)
+{
+ nrfx_err_t err_code;
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ /* Check power state*/
+ if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ /* Check data address */
+ if (!nrfx_is_in_ram(p_buf))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ /* Check data size */
+ if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size)
+ {
+ err_code = NRFX_ERROR_INVALID_LENGTH;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ nrf_twis_tx_prepare(p_instance->p_reg,
+ (uint8_t const *)p_buf,
+ (nrf_twis_amount_t)size);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
+ void * p_buf,
+ size_t size)
+{
+ nrfx_err_t err_code;
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ /* Check power state*/
+ if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ /* Check data address */
+ if (!nrfx_is_in_ram(p_buf))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ /* Check data size */
+ if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size)
+ {
+ err_code = NRFX_ERROR_INVALID_LENGTH;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ nrf_twis_rx_prepare(p_instance->p_reg,
+ (uint8_t *)p_buf,
+ (nrf_twis_amount_t)size);
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
+}
+
+bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
+}
+
+bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
+}
+
+bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
+}
+
+bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
+{
+ nrfx_twis_preprocess_status(p_instance);
+ twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
+ return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
+}
+
+
+#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
+void nrfx_twis_0_irq_handler(void)
+{
+ nrfx_twis_state_machine(NRF_TWIS0, &m_cb[NRFX_TWIS0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
+void nrfx_twis_1_irq_handler(void)
+{
+ nrfx_twis_state_machine(NRF_TWIS1, &m_cb[NRFX_TWIS1_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uart.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uart.c
new file mode 100644
index 0000000..8c5f487
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uart.c
@@ -0,0 +1,649 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_UART_ENABLED)
+
+#if !NRFX_CHECK(NRFX_UART0_ENABLED)
+#error "No enabled UART instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_uart.h>
+#include "prs/nrfx_prs.h"
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE UART
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_UART_EVENT_ERROR ? "NRF_UART_EVENT_ERROR" : \
+ "UNKNOWN EVENT")
+
+
+#define TX_COUNTER_ABORT_REQ_VALUE UINT32_MAX
+
+typedef struct
+{
+ void * p_context;
+ nrfx_uart_event_handler_t handler;
+ uint8_t const * p_tx_buffer;
+ uint8_t * p_rx_buffer;
+ uint8_t * p_rx_secondary_buffer;
+ size_t tx_buffer_length;
+ size_t rx_buffer_length;
+ size_t rx_secondary_buffer_length;
+ volatile size_t tx_counter;
+ volatile size_t rx_counter;
+ volatile bool tx_abort;
+ bool rx_enabled;
+ nrfx_drv_state_t state;
+} uart_control_block_t;
+static uart_control_block_t m_cb[NRFX_UART_ENABLED_COUNT];
+
+static void apply_config(nrfx_uart_t const * p_instance,
+ nrfx_uart_config_t const * p_config)
+{
+ if (p_config->pseltxd != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_pin_set(p_config->pseltxd);
+ nrf_gpio_cfg_output(p_config->pseltxd);
+ }
+ if (p_config->pselrxd != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
+ }
+
+ nrf_uart_baudrate_set(p_instance->p_reg, p_config->baudrate);
+ nrf_uart_configure(p_instance->p_reg, p_config->parity, p_config->hwfc);
+ nrf_uart_txrx_pins_set(p_instance->p_reg, p_config->pseltxd, p_config->pselrxd);
+ if (p_config->hwfc == NRF_UART_HWFC_ENABLED)
+ {
+ if (p_config->pselcts != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
+ }
+ if (p_config->pselrts != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_pin_set(p_config->pselrts);
+ nrf_gpio_cfg_output(p_config->pselrts);
+ }
+ nrf_uart_hwfc_pins_set(p_instance->p_reg, p_config->pselrts, p_config->pselcts);
+ }
+}
+
+static void interrupts_enable(nrfx_uart_t const * p_instance,
+ uint8_t interrupt_priority)
+{
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
+ nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_TXDRDY |
+ NRF_UART_INT_MASK_RXTO);
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
+ interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
+}
+
+static void interrupts_disable(nrfx_uart_t const * p_instance)
+{
+ nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_TXDRDY |
+ NRF_UART_INT_MASK_ERROR |
+ NRF_UART_INT_MASK_RXTO);
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
+}
+
+static void pins_to_default(nrfx_uart_t const * p_instance)
+{
+ /* Reset pins to default states */
+ uint32_t txd;
+ uint32_t rxd;
+ uint32_t rts;
+ uint32_t cts;
+
+ txd = nrf_uart_tx_pin_get(p_instance->p_reg);
+ rxd = nrf_uart_rx_pin_get(p_instance->p_reg);
+ rts = nrf_uart_rts_pin_get(p_instance->p_reg);
+ cts = nrf_uart_cts_pin_get(p_instance->p_reg);
+ nrf_uart_txrx_pins_disconnect(p_instance->p_reg);
+ nrf_uart_hwfc_pins_disconnect(p_instance->p_reg);
+
+ if (txd != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(txd);
+ }
+ if (rxd != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(rxd);
+ }
+ if (cts != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(cts);
+ }
+ if (rts != NRF_UART_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(rts);
+ }
+}
+
+nrfx_err_t nrfx_uart_init(nrfx_uart_t const * p_instance,
+ nrfx_uart_config_t const * p_config,
+ nrfx_uart_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_UART_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_UART0_ENABLED)
+ nrfx_uart_0_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_reg,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ apply_config(p_instance, p_config);
+
+ p_cb->handler = event_handler;
+ p_cb->p_context = p_config->p_context;
+
+ if (p_cb->handler)
+ {
+ interrupts_enable(p_instance, p_config->interrupt_priority);
+ }
+
+ nrf_uart_enable(p_instance->p_reg);
+ p_cb->rx_buffer_length = 0;
+ p_cb->rx_secondary_buffer_length = 0;
+ p_cb->rx_enabled = false;
+ p_cb->tx_buffer_length = 0;
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_uart_uninit(nrfx_uart_t const * p_instance)
+{
+ uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ nrf_uart_disable(p_instance->p_reg);
+
+ if (p_cb->handler)
+ {
+ interrupts_disable(p_instance);
+ }
+
+ pins_to_default(p_instance);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_reg);
+#endif
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+ p_cb->handler = NULL;
+ NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
+}
+
+static void tx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
+{
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
+ uint8_t txd = p_cb->p_tx_buffer[p_cb->tx_counter];
+ p_cb->tx_counter++;
+ nrf_uart_txd_set(p_uart, txd);
+}
+
+static bool tx_blocking(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
+{
+ while (p_cb->tx_counter < p_cb->tx_buffer_length)
+ {
+ // Wait until the transmitter is ready to accept a new byte.
+ // Exit immediately if the transfer has been aborted.
+ while (!nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
+ {
+ if (p_cb->tx_abort)
+ {
+ return false;
+ }
+ }
+
+ tx_byte(p_uart, p_cb);
+ }
+
+ return true;
+}
+
+nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
+ uint8_t const * p_data,
+ size_t length)
+{
+ uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
+ NRFX_ASSERT(p_data);
+ NRFX_ASSERT(length > 0);
+
+ nrfx_err_t err_code;
+
+ if (nrfx_uart_tx_in_progress(p_instance))
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ p_cb->tx_buffer_length = length;
+ p_cb->p_tx_buffer = p_data;
+ p_cb->tx_counter = 0;
+ p_cb->tx_abort = false;
+
+ NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
+ NRFX_LOG_DEBUG("Tx data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
+ p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
+
+ err_code = NRFX_SUCCESS;
+
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTTX);
+
+ tx_byte(p_instance->p_reg, p_cb);
+
+ if (p_cb->handler == NULL)
+ {
+ if (!tx_blocking(p_instance->p_reg, p_cb))
+ {
+ // The transfer has been aborted.
+ err_code = NRFX_ERROR_FORBIDDEN;
+ }
+ else
+ {
+ // Wait until the last byte is completely transmitted.
+ while (!nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_TXDRDY))
+ {}
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
+ }
+ p_cb->tx_buffer_length = 0;
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance)
+{
+ return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0);
+}
+
+static void rx_enable(nrfx_uart_t const * p_instance)
+{
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
+}
+
+static void rx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
+{
+ if (!p_cb->rx_buffer_length)
+ {
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
+ // Byte received when buffer is not set - data lost.
+ (void) nrf_uart_rxd_get(p_uart);
+ return;
+ }
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
+ p_cb->p_rx_buffer[p_cb->rx_counter] = nrf_uart_rxd_get(p_uart);
+ p_cb->rx_counter++;
+}
+
+nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
+ uint8_t * p_data,
+ size_t length)
+{
+ uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
+ NRFX_ASSERT(p_data);
+ NRFX_ASSERT(length > 0);
+
+ nrfx_err_t err_code;
+
+ bool second_buffer = false;
+
+ if (p_cb->handler)
+ {
+ nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ }
+ if (p_cb->rx_buffer_length != 0)
+ {
+ if (p_cb->rx_secondary_buffer_length != 0)
+ {
+ if (p_cb->handler)
+ {
+ nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ }
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ second_buffer = true;
+ }
+
+ if (!second_buffer)
+ {
+ p_cb->rx_buffer_length = length;
+ p_cb->p_rx_buffer = p_data;
+ p_cb->rx_counter = 0;
+ p_cb->rx_secondary_buffer_length = 0;
+ }
+ else
+ {
+ p_cb->p_rx_secondary_buffer = p_data;
+ p_cb->rx_secondary_buffer_length = length;
+ }
+
+ NRFX_LOG_INFO("Transfer rx_len: %d.", length);
+
+ if ((!p_cb->rx_enabled) && (!second_buffer))
+ {
+ rx_enable(p_instance);
+ }
+
+ if (p_cb->handler == NULL)
+ {
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
+
+ bool rxrdy;
+ bool rxto;
+ bool error;
+ do
+ {
+ do
+ {
+ error = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_ERROR);
+ rxrdy = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
+ rxto = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXTO);
+ } while ((!rxrdy) && (!rxto) && (!error));
+
+ if (error || rxto)
+ {
+ break;
+ }
+ rx_byte(p_instance->p_reg, p_cb);
+ } while (p_cb->rx_buffer_length > p_cb->rx_counter);
+
+ p_cb->rx_buffer_length = 0;
+ if (error)
+ {
+ err_code = NRFX_ERROR_INTERNAL;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (rxto)
+ {
+ err_code = NRFX_ERROR_FORBIDDEN;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (p_cb->rx_enabled)
+ {
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
+ }
+ else
+ {
+ // Skip stopping RX if driver is forced to be enabled.
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
+ }
+ }
+ else
+ {
+ nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ }
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance)
+{
+ return nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
+}
+
+void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance)
+{
+ if (!m_cb[p_instance->drv_inst_idx].rx_enabled)
+ {
+ rx_enable(p_instance);
+ m_cb[p_instance->drv_inst_idx].rx_enabled = true;
+ }
+}
+
+void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance)
+{
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
+ m_cb[p_instance->drv_inst_idx].rx_enabled = false;
+}
+
+uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance)
+{
+ nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
+ return nrf_uart_errorsrc_get_and_clear(p_instance->p_reg);
+}
+
+static void rx_done_event(uart_control_block_t * p_cb,
+ size_t bytes,
+ uint8_t * p_data)
+{
+ nrfx_uart_event_t event;
+
+ event.type = NRFX_UART_EVT_RX_DONE;
+ event.data.rxtx.bytes = bytes;
+ event.data.rxtx.p_data = p_data;
+
+ p_cb->handler(&event, p_cb->p_context);
+}
+
+static void tx_done_event(uart_control_block_t * p_cb,
+ size_t bytes)
+{
+ nrfx_uart_event_t event;
+
+ event.type = NRFX_UART_EVT_TX_DONE;
+ event.data.rxtx.bytes = bytes;
+ event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer;
+
+ p_cb->tx_buffer_length = 0;
+
+ p_cb->handler(&event, p_cb->p_context);
+}
+
+void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance)
+{
+ uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ p_cb->tx_abort = true;
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
+ if (p_cb->handler)
+ {
+ tx_done_event(p_cb, p_cb->tx_counter);
+ }
+
+ NRFX_LOG_INFO("TX transaction aborted.");
+}
+
+void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance)
+{
+ nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
+
+ NRFX_LOG_INFO("RX transaction aborted.");
+}
+
+static void uart_irq_handler(NRF_UART_Type * p_uart,
+ uart_control_block_t * p_cb)
+{
+ if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) &&
+ nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR))
+ {
+ nrfx_uart_event_t event;
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR);
+ NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_UART_EVENT_ERROR));
+ nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ if (!p_cb->rx_enabled)
+ {
+ nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
+ }
+ event.type = NRFX_UART_EVT_ERROR;
+ event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(p_uart);
+ event.data.error.rxtx.bytes = p_cb->rx_buffer_length;
+ event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
+
+ // Abort transfer.
+ p_cb->rx_buffer_length = 0;
+ p_cb->rx_secondary_buffer_length = 0;
+
+ p_cb->handler(&event,p_cb->p_context);
+ }
+ else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) &&
+ nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY))
+ {
+ rx_byte(p_uart, p_cb);
+ if (p_cb->rx_buffer_length == p_cb->rx_counter)
+ {
+ if (p_cb->rx_secondary_buffer_length)
+ {
+ uint8_t * p_data = p_cb->p_rx_buffer;
+ size_t rx_counter = p_cb->rx_counter;
+
+ // Switch to secondary buffer.
+ p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
+ p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
+ p_cb->rx_secondary_buffer_length = 0;
+ p_cb->rx_counter = 0;
+ rx_done_event(p_cb, rx_counter, p_data);
+ }
+ else
+ {
+ if (!p_cb->rx_enabled)
+ {
+ nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
+ }
+ nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
+ NRF_UART_INT_MASK_ERROR);
+ p_cb->rx_buffer_length = 0;
+ rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
+ }
+ }
+ }
+
+ if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
+ {
+ if (p_cb->tx_counter < p_cb->tx_buffer_length &&
+ !p_cb->tx_abort)
+ {
+ tx_byte(p_uart, p_cb);
+ }
+ else
+ {
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
+ if (p_cb->tx_buffer_length)
+ {
+ tx_done_event(p_cb, p_cb->tx_buffer_length);
+ }
+ }
+ }
+
+ if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO))
+ {
+ nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO);
+
+ // RXTO event may be triggered as a result of abort call. In th
+ if (p_cb->rx_enabled)
+ {
+ nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX);
+ }
+ if (p_cb->rx_buffer_length)
+ {
+ p_cb->rx_buffer_length = 0;
+ rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
+ }
+ }
+}
+
+#if NRFX_CHECK(NRFX_UART0_ENABLED)
+void nrfx_uart_0_irq_handler(void)
+{
+ uart_irq_handler(NRF_UART0, &m_cb[NRFX_UART0_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_UART_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uarte.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uarte.c
new file mode 100644
index 0000000..1d5bf09
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_uarte.c
@@ -0,0 +1,583 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_UARTE_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_UARTE0_ENABLED) || NRFX_CHECK(NRFX_UARTE1_ENABLED))
+#error "No enabled UARTE instances. Check <nrfx_config.h>."
+#endif
+
+#include <nrfx_uarte.h>
+#include "prs/nrfx_prs.h"
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE UARTE
+#include <nrfx_log.h>
+
+#define EVT_TO_STR(event) \
+ (event == NRF_UARTE_EVENT_ERROR ? "NRF_UARTE_EVENT_ERROR" : \
+ "UNKNOWN EVENT")
+
+#define UARTEX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
+ (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+ NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
+
+#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
+#define UARTE0_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE0, __VA_ARGS__)
+#else
+#define UARTE0_LENGTH_VALIDATE(...) 0
+#endif
+
+#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
+#define UARTE1_LENGTH_VALIDATE(...) UARTEX_LENGTH_VALIDATE(UARTE1, __VA_ARGS__)
+#else
+#define UARTE1_LENGTH_VALIDATE(...) 0
+#endif
+
+#define UARTE_LENGTH_VALIDATE(drv_inst_idx, length) \
+ (UARTE0_LENGTH_VALIDATE(drv_inst_idx, length, 0) || \
+ UARTE1_LENGTH_VALIDATE(drv_inst_idx, length, 0))
+
+
+typedef struct
+{
+ void * p_context;
+ nrfx_uarte_event_handler_t handler;
+ uint8_t const * p_tx_buffer;
+ uint8_t * p_rx_buffer;
+ uint8_t * p_rx_secondary_buffer;
+ size_t tx_buffer_length;
+ size_t rx_buffer_length;
+ size_t rx_secondary_buffer_length;
+ nrfx_drv_state_t state;
+} uarte_control_block_t;
+static uarte_control_block_t m_cb[NRFX_UARTE_ENABLED_COUNT];
+
+static void apply_config(nrfx_uarte_t const * p_instance,
+ nrfx_uarte_config_t const * p_config)
+{
+ if (p_config->pseltxd != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_pin_set(p_config->pseltxd);
+ nrf_gpio_cfg_output(p_config->pseltxd);
+ }
+ if (p_config->pselrxd != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
+ }
+
+ nrf_uarte_baudrate_set(p_instance->p_reg, p_config->baudrate);
+ nrf_uarte_configure(p_instance->p_reg, p_config->parity, p_config->hwfc);
+ nrf_uarte_txrx_pins_set(p_instance->p_reg, p_config->pseltxd, p_config->pselrxd);
+ if (p_config->hwfc == NRF_UARTE_HWFC_ENABLED)
+ {
+ if (p_config->pselcts != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
+ }
+ if (p_config->pselrts != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_pin_set(p_config->pselrts);
+ nrf_gpio_cfg_output(p_config->pselrts);
+ }
+ nrf_uarte_hwfc_pins_set(p_instance->p_reg, p_config->pselrts, p_config->pselcts);
+ }
+}
+
+static void interrupts_enable(nrfx_uarte_t const * p_instance,
+ uint8_t interrupt_priority)
+{
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
+ nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ENDRX_MASK |
+ NRF_UARTE_INT_ENDTX_MASK |
+ NRF_UARTE_INT_ERROR_MASK |
+ NRF_UARTE_INT_RXTO_MASK);
+ NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
+ interrupt_priority);
+ NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
+}
+
+static void interrupts_disable(nrfx_uarte_t const * p_instance)
+{
+ nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ENDRX_MASK |
+ NRF_UARTE_INT_ENDTX_MASK |
+ NRF_UARTE_INT_ERROR_MASK |
+ NRF_UARTE_INT_RXTO_MASK);
+ NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
+}
+
+static void pins_to_default(nrfx_uarte_t const * p_instance)
+{
+ /* Reset pins to default states */
+ uint32_t txd;
+ uint32_t rxd;
+ uint32_t rts;
+ uint32_t cts;
+
+ txd = nrf_uarte_tx_pin_get(p_instance->p_reg);
+ rxd = nrf_uarte_rx_pin_get(p_instance->p_reg);
+ rts = nrf_uarte_rts_pin_get(p_instance->p_reg);
+ cts = nrf_uarte_cts_pin_get(p_instance->p_reg);
+ nrf_uarte_txrx_pins_disconnect(p_instance->p_reg);
+ nrf_uarte_hwfc_pins_disconnect(p_instance->p_reg);
+
+ if (txd != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(txd);
+ }
+ if (rxd != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(rxd);
+ }
+ if (cts != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(cts);
+ }
+ if (rts != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_default(rts);
+ }
+}
+
+nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance,
+ nrfx_uarte_config_t const * p_config,
+ nrfx_uarte_event_handler_t event_handler)
+{
+ NRFX_ASSERT(p_config);
+ uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ nrfx_err_t err_code = NRFX_SUCCESS;
+
+ if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ static nrfx_irq_handler_t const irq_handlers[NRFX_UARTE_ENABLED_COUNT] = {
+ #if NRFX_CHECK(NRFX_UARTE0_ENABLED)
+ nrfx_uarte_0_irq_handler,
+ #endif
+ #if NRFX_CHECK(NRFX_UARTE1_ENABLED)
+ nrfx_uarte_1_irq_handler,
+ #endif
+ };
+ if (nrfx_prs_acquire(p_instance->p_reg,
+ irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
+
+ apply_config(p_instance, p_config);
+
+ p_cb->handler = event_handler;
+ p_cb->p_context = p_config->p_context;
+
+ if (p_cb->handler)
+ {
+ interrupts_enable(p_instance, p_config->interrupt_priority);
+ }
+
+ nrf_uarte_enable(p_instance->p_reg);
+ p_cb->rx_buffer_length = 0;
+ p_cb->rx_secondary_buffer_length = 0;
+ p_cb->tx_buffer_length = 0;
+ p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance)
+{
+ uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ nrf_uarte_disable(p_instance->p_reg);
+
+ if (p_cb->handler)
+ {
+ interrupts_disable(p_instance);
+ }
+
+ pins_to_default(p_instance);
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+ nrfx_prs_release(p_instance->p_reg);
+#endif
+
+ p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+ p_cb->handler = NULL;
+ NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
+}
+
+nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
+ uint8_t const * p_data,
+ size_t length)
+{
+ uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+ NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
+ NRFX_ASSERT(p_data);
+ NRFX_ASSERT(length > 0);
+ NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length));
+
+ nrfx_err_t err_code;
+
+ // EasyDMA requires that transfer buffers are placed in DataRAM,
+ // signal error if the are not.
+ if (!nrfx_is_in_ram(p_data))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ if (nrfx_uarte_tx_in_progress(p_instance))
+ {
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ p_cb->tx_buffer_length = length;
+ p_cb->p_tx_buffer = p_data;
+
+ NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
+ NRFX_LOG_DEBUG("Tx data:");
+ NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
+ p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
+
+ err_code = NRFX_SUCCESS;
+
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
+ nrf_uarte_tx_buffer_set(p_instance->p_reg, p_cb->p_tx_buffer, p_cb->tx_buffer_length);
+ nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTTX);
+
+ if (p_cb->handler == NULL)
+ {
+ bool endtx;
+ bool txstopped;
+ do
+ {
+ endtx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
+ txstopped = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
+ }
+ while ((!endtx) && (!txstopped));
+
+ if (txstopped)
+ {
+ err_code = NRFX_ERROR_FORBIDDEN;
+ }
+ p_cb->tx_buffer_length = 0;
+ }
+
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+bool nrfx_uarte_tx_in_progress(nrfx_uarte_t const * p_instance)
+{
+ return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0);
+}
+
+nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance,
+ uint8_t * p_data,
+ size_t length)
+{
+ uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
+ NRFX_ASSERT(p_data);
+ NRFX_ASSERT(length > 0);
+ NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length));
+
+ nrfx_err_t err_code;
+
+ // EasyDMA requires that transfer buffers are placed in DataRAM,
+ // signal error if the are not.
+ if (!nrfx_is_in_ram(p_data))
+ {
+ err_code = NRFX_ERROR_INVALID_ADDR;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ bool second_buffer = false;
+
+ if (p_cb->handler)
+ {
+ nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
+ NRF_UARTE_INT_ENDRX_MASK);
+ }
+ if (p_cb->rx_buffer_length != 0)
+ {
+ if (p_cb->rx_secondary_buffer_length != 0)
+ {
+ if (p_cb->handler)
+ {
+ nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
+ NRF_UARTE_INT_ENDRX_MASK);
+ }
+ err_code = NRFX_ERROR_BUSY;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+ second_buffer = true;
+ }
+
+ if (!second_buffer)
+ {
+ p_cb->rx_buffer_length = length;
+ p_cb->p_rx_buffer = p_data;
+ p_cb->rx_secondary_buffer_length = 0;
+ }
+ else
+ {
+ p_cb->p_rx_secondary_buffer = p_data;
+ p_cb->rx_secondary_buffer_length = length;
+ }
+
+ NRFX_LOG_INFO("Transfer rx_len: %d.", length);
+
+ err_code = NRFX_SUCCESS;
+
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
+ nrf_uarte_rx_buffer_set(p_instance->p_reg, p_data, length);
+ if (!second_buffer)
+ {
+ nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTRX);
+ }
+ else
+ {
+ nrf_uarte_shorts_enable(p_instance->p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);
+ }
+
+ if (m_cb[p_instance->drv_inst_idx].handler == NULL)
+ {
+ bool endrx;
+ bool rxto;
+ bool error;
+ do {
+ endrx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
+ rxto = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_RXTO);
+ error = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
+ } while ((!endrx) && (!rxto) && (!error));
+
+ m_cb[p_instance->drv_inst_idx].rx_buffer_length = 0;
+
+ if (error)
+ {
+ err_code = NRFX_ERROR_INTERNAL;
+ }
+
+ if (rxto)
+ {
+ err_code = NRFX_ERROR_FORBIDDEN;
+ }
+ }
+ else
+ {
+ nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK |
+ NRF_UARTE_INT_ENDRX_MASK);
+ }
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+bool nrfx_uarte_rx_ready(nrfx_uarte_t const * p_instance)
+{
+ return nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX);
+}
+
+uint32_t nrfx_uarte_errorsrc_get(nrfx_uarte_t const * p_instance)
+{
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ERROR);
+ return nrf_uarte_errorsrc_get_and_clear(p_instance->p_reg);
+}
+
+static void rx_done_event(uarte_control_block_t * p_cb,
+ size_t bytes,
+ uint8_t * p_data)
+{
+ nrfx_uarte_event_t event;
+
+ event.type = NRFX_UARTE_EVT_RX_DONE;
+ event.data.rxtx.bytes = bytes;
+ event.data.rxtx.p_data = p_data;
+
+ p_cb->handler(&event, p_cb->p_context);
+}
+
+static void tx_done_event(uarte_control_block_t * p_cb,
+ size_t bytes)
+{
+ nrfx_uarte_event_t event;
+
+ event.type = NRFX_UARTE_EVT_TX_DONE;
+ event.data.rxtx.bytes = bytes;
+ event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer;
+
+ p_cb->tx_buffer_length = 0;
+
+ p_cb->handler(&event, p_cb->p_context);
+}
+
+void nrfx_uarte_tx_abort(nrfx_uarte_t const * p_instance)
+{
+ uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+ nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
+ nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPTX);
+ if (p_cb->handler == NULL)
+ {
+ while (!nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED))
+ {}
+ }
+ NRFX_LOG_INFO("TX transaction aborted.");
+}
+
+void nrfx_uarte_rx_abort(nrfx_uarte_t const * p_instance)
+{
+ nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPRX);
+ NRFX_LOG_INFO("RX transaction aborted.");
+}
+
+static void uarte_irq_handler(NRF_UARTE_Type * p_uarte,
+ uarte_control_block_t * p_cb)
+{
+ if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ERROR))
+ {
+ nrfx_uarte_event_t event;
+
+ nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ERROR);
+
+ event.type = NRFX_UARTE_EVT_ERROR;
+ event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(p_uarte);
+ event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(p_uarte);
+ event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
+
+ // Abort transfer.
+ p_cb->rx_buffer_length = 0;
+ p_cb->rx_secondary_buffer_length = 0;
+
+ p_cb->handler(&event, p_cb->p_context);
+ }
+ else if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDRX))
+ {
+ nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDRX);
+ size_t amount = nrf_uarte_rx_amount_get(p_uarte);
+ // If the transfer was stopped before completion, amount of transfered bytes
+ // will not be equal to the buffer length. Interrupted transfer is ignored.
+ if (amount == p_cb->rx_buffer_length)
+ {
+ if (p_cb->rx_secondary_buffer_length)
+ {
+ uint8_t * p_data = p_cb->p_rx_buffer;
+ nrf_uarte_shorts_disable(p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX);
+ p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
+ p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
+ p_cb->rx_secondary_buffer_length = 0;
+ rx_done_event(p_cb, amount, p_data);
+ }
+ else
+ {
+ p_cb->rx_buffer_length = 0;
+ rx_done_event(p_cb, amount, p_cb->p_rx_buffer);
+ }
+ }
+ }
+
+ if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_RXTO))
+ {
+ nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_RXTO);
+ if (p_cb->rx_buffer_length)
+ {
+ p_cb->rx_buffer_length = 0;
+ rx_done_event(p_cb, nrf_uarte_rx_amount_get(p_uarte), p_cb->p_rx_buffer);
+ }
+ }
+
+ if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDTX))
+ {
+ nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDTX);
+ if (p_cb->tx_buffer_length)
+ {
+ tx_done_event(p_cb, nrf_uarte_tx_amount_get(p_uarte));
+ }
+ }
+}
+
+#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
+void nrfx_uarte_0_irq_handler(void)
+{
+ uarte_irq_handler(NRF_UARTE0, &m_cb[NRFX_UARTE0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_UARTE1_ENABLED)
+void nrfx_uarte_1_irq_handler(void)
+{
+ uarte_irq_handler(NRF_UARTE1, &m_cb[NRFX_UARTE1_INST_IDX]);
+}
+#endif
+
+#endif // NRFX_CHECK(NRFX_UARTE_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_wdt.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_wdt.c
new file mode 100644
index 0000000..d4d33b1
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_wdt.c
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_WDT_ENABLED)
+#include <nrfx_wdt.h>
+
+#define NRFX_LOG_MODULE WDT
+#include <nrfx_log.h>
+
+
+/**@brief WDT event handler. */
+static nrfx_wdt_event_handler_t m_wdt_event_handler;
+
+/**@brief WDT state. */
+static nrfx_drv_state_t m_state;
+
+/**@brief WDT alloc table. */
+static uint32_t m_alloc_index;
+
+/**@brief WDT interrupt handler. */
+void nrfx_wdt_irq_handler(void)
+{
+ if (nrf_wdt_int_enable_check(NRF_WDT_INT_TIMEOUT_MASK) == true)
+ {
+ nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT);
+ m_wdt_event_handler();
+ }
+}
+
+
+nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
+ nrfx_wdt_event_handler_t wdt_event_handler)
+{
+ NRFX_ASSERT(p_config);
+ NRFX_ASSERT(wdt_event_handler != NULL);
+ nrfx_err_t err_code;
+ m_wdt_event_handler = wdt_event_handler;
+
+ if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ m_state = NRFX_DRV_STATE_INITIALIZED;
+ }
+ else
+ {
+ err_code = NRFX_ERROR_INVALID_STATE;
+ NRFX_LOG_WARNING("Function: %s, error code: %s.",
+ __func__,
+ NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+ }
+
+ nrf_wdt_behaviour_set(p_config->behaviour);
+
+ nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000);
+
+ NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
+ NRFX_IRQ_ENABLE(WDT_IRQn);
+
+ err_code = NRFX_SUCCESS;
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+ return err_code;
+}
+
+
+void nrfx_wdt_enable(void)
+{
+ NRFX_ASSERT(m_alloc_index != 0);
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
+ nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK);
+ nrf_wdt_task_trigger(NRF_WDT_TASK_START);
+ m_state = NRFX_DRV_STATE_POWERED_ON;
+ NRFX_LOG_INFO("Enabled.");
+}
+
+
+void nrfx_wdt_feed(void)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ for (uint32_t i = 0; i < m_alloc_index; i++)
+ {
+ nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i));
+ }
+}
+
+nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id)
+{
+ nrfx_err_t result;
+ NRFX_ASSERT(p_channel_id);
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
+
+ NRFX_CRITICAL_SECTION_ENTER();
+ if (m_alloc_index < NRF_WDT_CHANNEL_NUMBER)
+ {
+ *p_channel_id = (nrfx_wdt_channel_id)(NRF_WDT_RR0 + m_alloc_index);
+ m_alloc_index++;
+ nrf_wdt_reload_request_enable(*p_channel_id);
+ result = NRFX_SUCCESS;
+ }
+ else
+ {
+ result = NRFX_ERROR_NO_MEM;
+ }
+ NRFX_CRITICAL_SECTION_EXIT();
+ NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(result));
+ return result;
+}
+
+void nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id)
+{
+ NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
+ nrf_wdt_reload_request_set(channel_id);
+}
+
+#endif // NRFX_CHECK(NRFX_WDT_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.c
new file mode 100644
index 0000000..e7a105f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.c
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <nrfx.h>
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+#include "nrfx_prs.h"
+
+#define NRFX_LOG_MODULE PRS
+#include <nrfx_log.h>
+
+#define LOG_FUNCTION_EXIT(level, ret_code) \
+ NRFX_LOG_##level("Function: %s, error code: %s.", \
+ __func__, \
+ NRFX_LOG_ERROR_STRING_GET(ret_code))
+
+
+typedef struct {
+ nrfx_irq_handler_t handler;
+ bool acquired;
+} prs_box_t;
+
+#define PRS_BOX_DEFINE(n) \
+ static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
+ void nrfx_prs_box_##n##_irq_handler(void) \
+ { \
+ NRFX_ASSERT(m_prs_box_##n.handler); \
+ m_prs_box_##n.handler(); \
+ }
+
+#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
+PRS_BOX_DEFINE(0)
+#endif
+#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
+PRS_BOX_DEFINE(1)
+#endif
+#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
+PRS_BOX_DEFINE(2)
+#endif
+#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
+PRS_BOX_DEFINE(3)
+#endif
+#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
+PRS_BOX_DEFINE(4)
+#endif
+
+
+static prs_box_t * prs_box_get(void const * p_base_addr)
+{
+#if !defined(IS_PRS_BOX)
+#define IS_PRS_BOX(n, p_base_addr) ((p_base_addr) == NRFX_PRS_BOX_##n##_ADDR)
+#endif
+
+#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
+ if (IS_PRS_BOX(0, p_base_addr)) { return &m_prs_box_0; }
+ else
+#endif
+#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
+ if (IS_PRS_BOX(1, p_base_addr)) { return &m_prs_box_1; }
+ else
+#endif
+#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
+ if (IS_PRS_BOX(2, p_base_addr)) { return &m_prs_box_2; }
+ else
+#endif
+#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
+ if (IS_PRS_BOX(3, p_base_addr)) { return &m_prs_box_3; }
+ else
+#endif
+#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
+ if (IS_PRS_BOX(4, p_base_addr)) { return &m_prs_box_4; }
+ else
+#endif
+ {
+ return NULL;
+ }
+}
+
+nrfx_err_t nrfx_prs_acquire(void const * p_base_addr,
+ nrfx_irq_handler_t irq_handler)
+{
+ NRFX_ASSERT(p_base_addr);
+
+ nrfx_err_t ret_code;
+
+ prs_box_t * p_box = prs_box_get(p_base_addr);
+ if (p_box != NULL)
+ {
+ bool busy = false;
+
+ NRFX_CRITICAL_SECTION_ENTER();
+ if (p_box->acquired)
+ {
+ busy = true;
+ }
+ else
+ {
+ p_box->handler = irq_handler;
+ p_box->acquired = true;
+ }
+ NRFX_CRITICAL_SECTION_EXIT();
+
+ if (busy)
+ {
+ ret_code = NRFX_ERROR_BUSY;
+ LOG_FUNCTION_EXIT(WARNING, ret_code);
+ return ret_code;
+ }
+ }
+
+ ret_code = NRFX_SUCCESS;
+ LOG_FUNCTION_EXIT(INFO, ret_code);
+ return ret_code;
+}
+
+void nrfx_prs_release(void const * p_base_addr)
+{
+ NRFX_ASSERT(p_base_addr);
+
+ prs_box_t * p_box = prs_box_get(p_base_addr);
+ if (p_box != NULL)
+ {
+ p_box->handler = NULL;
+ p_box->acquired = false;
+ }
+}
+
+
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.h
new file mode 100644
index 0000000..f585fa1
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/prs/nrfx_prs.h
@@ -0,0 +1,140 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRFX_PRS_H__
+#define NRFX_PRS_H__
+
+#include <nrfx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_prs Peripheral Resource Sharing (PRS)
+ * @{
+ * @ingroup nrfx
+ *
+ * @brief Peripheral Resource Sharing interface (PRS).
+ */
+
+#if defined(NRF51)
+ // SPI0, TWI0
+ #define NRFX_PRS_BOX_0_ADDR NRF_SPI0
+ // SPI1, SPIS1, TWI1
+ #define NRFX_PRS_BOX_1_ADDR NRF_SPI1
+#elif defined(NRF52810_XXAA)
+ // TWIM0, TWIS0
+ #define NRFX_PRS_BOX_0_ADDR NRF_TWIM0
+ // SPIM0, SPIS0
+ #define NRFX_PRS_BOX_1_ADDR NRF_SPIM0
+#elif defined(NRF52832_XXAA) || defined (NRF52832_XXAB)
+ // SPIM0, SPIS0, TWIM0, TWIS0, SPI0, TWI0
+ #define NRFX_PRS_BOX_0_ADDR NRF_SPIM0
+ // SPIM1, SPIS1, TWIM1, TWIS1, SPI1, TWI1
+ #define NRFX_PRS_BOX_1_ADDR NRF_SPIM1
+ // SPIM2, SPIS2, SPI2
+ #define NRFX_PRS_BOX_2_ADDR NRF_SPIM2
+ // COMP, LPCOMP
+ #define NRFX_PRS_BOX_3_ADDR NRF_COMP
+ // UARTE0, UART0
+ #define NRFX_PRS_BOX_4_ADDR NRF_UARTE0
+#elif defined(NRF52840_XXAA)
+ // SPIM0, SPIS0, TWIM0, TWIS0, SPI0, TWI0
+ #define NRFX_PRS_BOX_0_ADDR NRF_SPIM0
+ // SPIM1, SPIS1, TWIM1, TWIS1, SPI1, TWI1
+ #define NRFX_PRS_BOX_1_ADDR NRF_SPIM1
+ // SPIM2, SPIS2, SPI2
+ #define NRFX_PRS_BOX_2_ADDR NRF_SPIM2
+ // COMP, LPCOMP
+ #define NRFX_PRS_BOX_3_ADDR NRF_COMP
+ // UARTE0, UART0
+ #define NRFX_PRS_BOX_4_ADDR NRF_UARTE0
+#else
+ #error "Unknown device."
+#endif
+
+/**
+ * @brief Function for acquiring shared peripheral resources associated with
+ * the specified peripheral.
+ *
+ * Certain resources and registers are shared among peripherals that have
+ * the same ID (for example: SPI0, SPIM0, SPIS0, TWI0, TWIM0, and TWIS0 in
+ * nRF52832). Only one of them can be utilized at a given time. This function
+ * reserves proper resources to be used by the specified peripheral.
+ * If NRFX_PRS_ENABLED is set to a non-zero value, IRQ handlers for peripherals
+ * that are sharing resources with others are implemented by the @ref nrfx_prs
+ * module instead of individual drivers. The drivers must then specify their
+ * interrupt handling routines and register them by using this function.
+ *
+ * @param[in] p_base_addr Requested peripheral base pointer.
+ * @param[in] irq_handler Interrupt handler to register.
+ *
+ * @retval NRFX_SUCCESS If resources were acquired successfully or the
+ * specified peripheral is not handled by the PRS
+ * subsystem and there is no need to acquire resources
+ * for it.
+ * @retval NRFX_ERROR_BUSY If resources were already acquired.
+ */
+nrfx_err_t nrfx_prs_acquire(void const * p_base_addr,
+ nrfx_irq_handler_t irq_handler);
+
+/**
+ * @brief Function for releasing shared resources reserved previously by
+ * @ref nrfx_prs_acquire() for the specified peripheral.
+ *
+ * @param[in] p_base_addr Released peripheral base pointer.
+ */
+void nrfx_prs_release(void const * p_base_addr);
+
+
+void nrfx_prs_box_0_irq_handler(void);
+void nrfx_prs_box_1_irq_handler(void);
+void nrfx_prs_box_2_irq_handler(void);
+void nrfx_prs_box_3_irq_handler(void);
+void nrfx_prs_box_4_irq_handler(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRFX_PRS_H__