Untitled diff

Created Diff never expires
10 removals
523 lines
101 additions
613 lines
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*
*
* The information contained herein is property of Nordic Semiconductor ASA.
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
*
* Licensees are granted free, non-transferable use of the information. NO
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
* the file.
*
*
*/
*/


#include "nrf_drv_gpiote.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_common.h"
#include "nrf_drv_common.h"
#include "nrf_drv_config.h"
#include "nrf_drv_config.h"
#include "app_util_platform.h"
#include "app_util_platform.h"
#include "nrf_assert.h"
#include "nrf_assert.h"


#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX)
#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX)
#define PIN_NOT_USED (-1)
#define PIN_NOT_USED (-1)
#define PIN_USED (-2)
#define PIN_USED (-2)
#define NO_CHANNELS (-1)
#define NO_CHANNELS (-1)
#define SENSE_FIELD_POS (6)
#define SENSE_FIELD_POS (6)
#define SENSE_FIELD_MASK (0xC0)
#define SENSE_FIELD_MASK (0xC0)


//lint -save -e661
//lint -save -e661
typedef struct
typedef struct
{
{
nrf_drv_state_t state;
nrf_drv_state_t state;
nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
int8_t pin_assignments[NUMBER_OF_PINS];
int8_t pin_assignments[NUMBER_OF_PINS];
int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
} control_block_t;
} control_block_t;


static control_block_t m_cb;
static control_block_t m_cb;


typedef void (*app_gpiote_event_handler_t)(uint32_t event_pins_low_to_high,
uint32_t event_pins_high_to_low);

/**@brief GPIOTE user type. */
typedef struct
{
uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */
uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */
uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */
uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */
app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */
} gpiote_user_t;

extern uint32_t m_enabled_users_mask; /**< Mask for tracking which users are enabled. */
extern uint8_t m_user_array_size; /**< Size of user array. */
extern uint8_t m_user_count; /**< Number of registered users. */
extern gpiote_user_t * mp_users; /**< Array of GPIOTE users. */

__STATIC_INLINE bool pin_in_use(uint32_t pin)
__STATIC_INLINE bool pin_in_use(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false;
return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false;
}
}


__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false;
return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false;
}
}


__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false;
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false;
}
}


__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false;
return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false;
}
}


__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= 0) ? true : false;
return (m_cb.pin_assignments[pin] >= 0) ? true : false;
}
}


__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
uint32_t channel_id,
uint32_t channel_id,
nrf_drv_gpiote_evt_handler_t handler,
nrf_drv_gpiote_evt_handler_t handler,
bool is_channel)
bool is_channel)
{
{
m_cb.pin_assignments[pin] = channel_id;
m_cb.pin_assignments[pin] = channel_id;
m_cb.handlers[channel_id] = handler;
m_cb.handlers[channel_id] = handler;
if (!is_channel)
if (!is_channel)
{
{
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin;
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin;
}
}
}
}


__STATIC_INLINE void pin_in_use_set(uint32_t pin)
__STATIC_INLINE void pin_in_use_set(uint32_t pin)
{
{
m_cb.pin_assignments[pin] = PIN_USED;
m_cb.pin_assignments[pin] = PIN_USED;
}
}


__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
{
{
m_cb.pin_assignments[pin] = PIN_NOT_USED;
m_cb.pin_assignments[pin] = PIN_NOT_USED;
}
}


__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
{
{
return m_cb.pin_assignments[pin];
return m_cb.pin_assignments[pin];
}
}


__STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel)
__STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel)
{
{
return m_cb.handlers_to_pins[port_channel];
return m_cb.handlers_to_pins[port_channel];
}
}


__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
{
{
return m_cb.handlers[channel];
return m_cb.handlers[channel];
}
}

void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins);
void sense_level_disable(uint32_t pins);


static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel)
static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel)
{
{
int8_t channel_id = NO_CHANNELS;
int8_t channel_id = NO_CHANNELS;
uint32_t i;
uint32_t i;


uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE;
uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE;
uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
//critical section
//critical section


for (i = start_idx; i < end_idx; i++)
for (i = start_idx; i < end_idx; i++)
{
{
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
{
{
pin_in_use_by_te_set(pin, i, handler, channel);
pin_in_use_by_te_set(pin, i, handler, channel);
channel_id = i;
channel_id = i;
break;
break;
}
}
}
}
//critical section
//critical section
return channel_id;
return channel_id;
}
}


static void channel_free(uint8_t channel_id)
static void channel_free(uint8_t channel_id)
{
{
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
if (channel_id >= NUMBER_OF_GPIO_TE)
if (channel_id >= NUMBER_OF_GPIO_TE)
{
{
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1;
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1;
}
}
}
}


ret_code_t nrf_drv_gpiote_init(void)
ret_code_t nrf_drv_gpiote_init(void)
{
{
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
{
return NRF_ERROR_INVALID_STATE;
return NRF_ERROR_INVALID_STATE;
}
}


uint8_t i;
uint8_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
for (i = 0; i < NUMBER_OF_PINS; i++)
{
{
pin_in_use_clear(i);
pin_in_use_clear(i);
}
}
for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
{
{
channel_free(i);
channel_free(i);
}
}


nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY);
nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
m_cb.state = NRF_DRV_STATE_INITIALIZED;
m_cb.state = NRF_DRV_STATE_INITIALIZED;


return NRF_SUCCESS;
return NRF_SUCCESS;
}
}


bool nrf_drv_gpiote_is_init(void)
bool nrf_drv_gpiote_is_init(void)
{
{
return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false;
return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false;
}
}


void nrf_drv_gpiote_uninit(void)
void nrf_drv_gpiote_uninit(void)
{
{
ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED);
ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED);


uint32_t i;
uint32_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
for (i = 0; i < NUMBER_OF_PINS; i++)
{
{
if (pin_in_use_as_non_task_out(i))
if (pin_in_use_as_non_task_out(i))
{
{
nrf_drv_gpiote_out_uninit(i);
nrf_drv_gpiote_out_uninit(i);
}
}
else if( pin_in_use_by_gpiote(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
/* 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.
* so it can be called on all pins used by GPIOTE.
*/
*/
nrf_drv_gpiote_in_uninit(i);
nrf_drv_gpiote_in_uninit(i);
}
}
}
}
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
}
}


ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config)
ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED);
ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED);
ASSERT(p_config);
ASSERT(p_config);


ret_code_t result = NRF_SUCCESS;
ret_code_t result = NRF_SUCCESS;


if (pin_in_use(pin))
if (pin_in_use(pin))
{
{
result = NRF_ERROR_INVALID_STATE;
result = NRF_ERROR_INVALID_STATE;
}
}
else
else
{
{
if (p_config->task_pin)
if (p_config->task_pin)
{
{
int8_t channel = channel_port_alloc(pin, NULL, true);
int8_t channel = channel_port_alloc(pin, NULL, true);


if (channel != NO_CHANNELS)
if (channel != NO_CHANNELS)
{
{
nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state);
nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state);
}
}
else
else
{
{
result = NRF_ERROR_NO_MEM;
result = NRF_ERROR_NO_MEM;
}
}
}
}
else
else
{
{
pin_in_use_set(pin);
pin_in_use_set(pin);
}
}


if (result == NRF_SUCCESS)
if (result == NRF_SUCCESS)
{
{
nrf_gpio_cfg_output(pin);
nrf_gpio_cfg_output(pin);


if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
{
{
nrf_gpio_pin_set(pin);
nrf_gpio_pin_set(pin);
}
}
else
else
{
{
nrf_gpio_pin_clear(pin);
nrf_gpio_pin_clear(pin);
}
}
}
}
}
}


return result;
return result;
}
}


void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));


if (pin_in_use_by_te(pin))
if (pin_in_use_by_te(pin))
{
{
channel_free((uint8_t)m_cb.pin_assignments[pin]);
channel_free((uint8_t)m_cb.pin_assignments[pin]);
}
}
pin_in_use_clear(pin);
pin_in_use_clear(pin);


nrf_gpio_cfg_default(pin);
nrf_gpio_cfg_default(pin);
}
}


void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))


nrf_gpio_pin_set(pin);
nrf_gpio_pin_set(pin);
}
}


void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))


nrf_gpio_pin_clear(pin);
nrf_gpio_pin_clear(pin);
}
}


void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))


nrf_gpio_pin_toggle(pin);
nrf_gpio_pin_toggle(pin);
}
}


void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
ASSERT(pin_in_use_by_te(pin))


nrf_gpiote_task_enable(m_cb.pin_assignments[pin]);
nrf_gpiote_task_enable(m_cb.pin_assignments[pin]);
}
}


void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
ASSERT(pin_in_use_by_te(pin))


nrf_gpiote_task_disable(m_cb.pin_assignments[pin]);
nrf_gpiote_task_disable(m_cb.pin_assignments[pin]);
}
}


uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin)
uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));


nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
return nrf_gpiote_task_addr_get(task);
return nrf_gpiote_task_addr_get(task);
}
}


void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state)
void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
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_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val);
nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val);
}
}


void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));


nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_task_set(task);
nrf_gpiote_task_set(task);
}
}


ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_in_config_t * p_config,
nrf_drv_gpiote_in_config_t * p_config,
nrf_drv_gpiote_evt_handler_t evt_handler)
nrf_drv_gpiote_evt_handler_t evt_handler)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ret_code_t result = NRF_SUCCESS;
ret_code_t result = NRF_SUCCESS;
/* Only one GPIOTE channel can be assigned to one physical pin. */
/* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
if (pin_in_use_by_gpiote(pin))
{
{
result = NRF_ERROR_INVALID_STATE;
result = NRF_ERROR_INVALID_STATE;
}
}
else
else
{
{
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
if (channel != NO_CHANNELS)
if (channel != NO_CHANNELS)
{
{
if (p_config->is_watcher)
if (p_config->is_watcher)
{
{
nrf_gpio_cfg_watcher(pin);
nrf_gpio_cfg_watcher(pin);
}
}
else
else
{
{
nrf_gpio_cfg_input(pin,p_config->pull);
nrf_gpio_cfg_input(pin,p_config->pull);
}
}


if (p_config->hi_accuracy)
if (p_config->hi_accuracy)
{
{
nrf_gpiote_event_configure(channel, pin,p_config->sense);
nrf_gpiote_event_configure(channel, pin,p_config->sense);
}
}
else
else
{
{
m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS;
m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS;
}
}
}
}
else
else
{
{
result = NRF_ERROR_NO_MEM;
result = NRF_ERROR_NO_MEM;
}
}
}
}
return result;
return result;
}
}


void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable)
void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
if (pin_in_use_by_port(pin))
{
{
uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE);
uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE);
nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
nrf_gpio_pin_sense_t sense;
nrf_gpio_pin_sense_t sense;
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
{
/* read current pin state and set for next sense to oposit */
/* read current pin state and set for next sense to oposit */
sense = (nrf_gpio_pins_read() & (1 << pin)) ?
sense = (nrf_gpio_pins_read() & (1 << pin)) ?
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
}
}
else
else
{
{
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
}
}
nrf_gpio_cfg_sense_set(pin,sense);
nrf_gpio_cfg_sense_set(pin,sense);
}
}
else if(pin_in_use_by_te(pin))
else if(pin_in_use_by_te(pin))
{
{
int32_t channel = (int32_t)channel_port_get(pin);
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel);
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel);
nrf_gpiote_event_enable(channel);
nrf_gpiote_event_enable(channel);


nrf_gpiote_event_clear(event);
nrf_gpiote_event_clear(event);
if (int_enable)
if (int_enable)
{
{
nrf_gpiote_int_enable(1 << channel);
nrf_gpiote_int_enable(1 << channel);
}
}
}
}
}
}


void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
if (pin_in_use_by_port(pin))
{
{
nrf_gpio_input_disconnect(pin);
nrf_gpio_input_disconnect(pin);
}
}
else if(pin_in_use_by_te(pin))
else if(pin_in_use_by_te(pin))
{
{
int32_t channel = (int32_t)channel_port_get(pin);
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_event_disable(channel);
nrf_gpiote_event_disable(channel);
nrf_gpiote_int_disable(1 << channel);
nrf_gpiote_int_disable(1 << channel);
}
}
}
}


void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
nrf_drv_gpiote_in_event_disable(pin);
nrf_drv_gpiote_in_event_disable(pin);
if(pin_in_use_by_te(pin))
if(pin_in_use_by_te(pin))
{
{
nrf_gpiote_te_default(channel_port_get(pin));
nrf_gpiote_te_default(channel_port_get(pin));
}
}
nrf_gpio_cfg_default(pin);
nrf_gpio_cfg_default(pin);
channel_free((uint8_t)channel_port_get(pin));
channel_free((uint8_t)channel_port_get(pin));
pin_in_use_clear(pin);
pin_in_use_clear(pin);
}
}


bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin)
bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
return nrf_gpio_pin_read(pin) ? true : false;
return nrf_gpio_pin_read(pin) ? true : false;
}
}


uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin)
uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));


nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin)));
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin)));
return nrf_gpiote_event_addr_get(event);
return nrf_gpiote_event_addr_get(event);
}
}


void GPIOTE_IRQHandler(void)
void GPIOTE_IRQHandler(void)
{
{
uint32_t status = 0;
uint32_t status = 0;
uint32_t input = 0;
uint32_t input = 0;
uint32_t i;
uint32_t pins_changed = 1;
uint32_t pins_sense_enabled = 0;
uint32_t pins_sense_disabled = 0;
uint32_t pins_state = NRF_GPIO->IN;


/* 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;
input = nrf_gpio_pins_read();
}

while (pins_changed)
{
// Check all users.
for (i = 0; i < m_user_count; i++)
{
gpiote_user_t * p_user = &mp_users[i];

// Check if user is enabled.
if (((1 << i) & m_enabled_users_mask) != 0)
{
uint32_t transition_pins;
uint32_t event_low_to_high = 0;
uint32_t event_high_to_low = 0;

pins_sense_enabled |= (p_user->pins_mask & ~pins_sense_disabled);

// Find set of pins on which there has been a transition.
transition_pins = (pins_state ^ ~p_user->sense_high_pins) & (p_user->pins_mask & ~pins_sense_disabled);

sense_level_disable(transition_pins);
pins_sense_disabled |= transition_pins;
pins_sense_enabled &= ~pins_sense_disabled;

// Call user event handler if an event has occurred.
event_high_to_low |= (~pins_state & p_user->pins_high_to_low_mask) & transition_pins;
event_low_to_high |= (pins_state & p_user->pins_low_to_high_mask) & transition_pins;

if ((event_low_to_high | event_high_to_low) != 0)
{
p_user->event_handler(event_low_to_high, event_high_to_low);
}
}
}

// Second read after setting sense.
// Check if any pins with sense enabled have changed while serving this interrupt.
pins_changed = (NRF_GPIO->IN ^ pins_state) & pins_sense_enabled;
pins_state ^= pins_changed;
}
// Now re-enabling sense on all pins that have sense disabled.
// Note: a new interrupt might fire immediatly.
for (i = 0; i < m_user_count; i++)
{
gpiote_user_t * p_user = &mp_users[i];

// Check if user is enabled.
if (((1 << i) & m_enabled_users_mask) != 0)
{
if (pins_sense_disabled & p_user->pins_mask)
{
sense_level_toggle(p_user, pins_sense_disabled & p_user->pins_mask);
}
}
}


/* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
/* 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;
nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
{
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(1 << i))
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))
{
{
nrf_gpiote_event_clear(event);
nrf_gpiote_event_clear(event);
status |= mask;
status |= mask;
}
}
mask <<= 1;
mask <<= 1;
event = (nrf_gpiote_events_t)((uint32_t)event + 4);
/* 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
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
* end of interrupt. */
* end of interrupt. */
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
{
{
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
input = nrf_gpio_pins_read();
input = nrf_gpio_pins_read();
}
}


/* Process pin events. */
/* Process pin events. */
if (status & NRF_GPIOTE_INT_IN_MASK)
if (status & NRF_GPIOTE_INT_IN_MASK)
{
{
mask = 1;
mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
{
if (mask & status)
if (mask & status)
{
{
nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);
handler(pin,polarity);
handler(pin,polarity);
}
}
mask <<= 1;
mask <<= 1;
}
}
}
}


if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
{
{
/* Process port event. */
/* Process port event. */
for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
{
{
uint8_t pin_and_sense = pin_from_port_get(i);
if (m_cb.port_handlers_pins[i] != PIN_NOT_USED)
nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
nrf_gpiote_polarity_t polarity =
(nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
mask = 1 << pin;
if (pin_in_use_by_port(pin))
{
{
uint8_t pin_and_sense = m_cb.port_handlers_pins[i];
nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
if (handler)
if (handler)
{
{
nrf_gpiote_polarity_t polarity =
(nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
mask = 1 << pin;
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
(!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) )
(!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) )
{
{
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
{
nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
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_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
nrf_gpio_cfg_sense_set(pin, next_sense);
nrf_gpio_cfg_sense_set(pin, next_sense);
}
}
handler(pin, polarity);
handler(pin, polarity);
}
}
}
}
}
}
}
}
}
}
}
}
//lint -restore
//lint -restore