<commit_before>/*
 * Copyright (c) 2018, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <sensor.h>

#include <nrfx_qdec.h>
#include <hal/nrf_gpio.h>

#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(qdec_nrfx);


#define FULL_ANGLE 360

/* limit range to avoid overflow when converting steps to degrees */
#define ACC_MAX (INT_MAX / FULL_ANGLE)
#define ACC_MIN (INT_MIN / FULL_ANGLE)


struct qdec_nrfx_data {
	s32_t                    acc;
	sensor_trigger_handler_t data_ready_handler;
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	u32_t                    pm_state;
#endif
};


static struct qdec_nrfx_data qdec_nrfx_data;

DEVICE_DECLARE(qdec_nrfx);


static void accumulate(struct qdec_nrfx_data *data, int16_t acc)
{
	unsigned int key = irq_lock();

	bool overflow = ((acc > 0) && (ACC_MAX - acc < data->acc)) ||
			((acc < 0) && (ACC_MIN - acc > data->acc));

	if (!overflow) {
		data->acc += acc;
	}

	irq_unlock(key);
}

static int qdec_nrfx_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;

	int16_t acc;
	int16_t accdbl;

	ARG_UNUSED(dev);

	LOG_DBG("");

	if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_ROTATION)) {
		return -ENOTSUP;
	}

	nrfx_qdec_accumulators_read(&acc, &accdbl);

	accumulate(data, acc);

	return 0;
}

static int qdec_nrfx_channel_get(struct device       *dev,
				 enum sensor_channel  chan,
				 struct sensor_value *val)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;
	unsigned int key;
	s32_t acc;

	ARG_UNUSED(dev);
	LOG_DBG("");

	if (chan != SENSOR_CHAN_ROTATION) {
		return -ENOTSUP;
	}

	key = irq_lock();
	acc = data->acc;
	data->acc = 0;
	irq_unlock(key);

	BUILD_ASSERT_MSG(DT_NORDIC_NRF_QDEC_QDEC_0_STEPS > 0,
			 "only positive number valid");
	BUILD_ASSERT_MSG(DT_NORDIC_NRF_QDEC_QDEC_0_STEPS <= 2148,
			 "overflow possible");

	val->val1 = (acc * FULL_ANGLE) / DT_NORDIC_NRF_QDEC_QDEC_0_STEPS;
	val->val2 = (acc * FULL_ANGLE)
		    - (val->val1 * DT_NORDIC_NRF_QDEC_QDEC_0_STEPS);
	if (val->val2 != 0) {
		val->val2 *= 1000000;
		val->val2 /= DT_NORDIC_NRF_QDEC_QDEC_0_STEPS;
	}

	return 0;
}

static int qdec_nrfx_trigger_set(struct device               *dev,
				 const struct sensor_trigger *trig,
				 sensor_trigger_handler_t     handler)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;
	unsigned int key;

	ARG_UNUSED(dev);
	LOG_DBG("");

	if (trig->type != SENSOR_TRIG_DATA_READY) {
		return -ENOTSUP;
	}

	if ((trig->chan != SENSOR_CHAN_ALL) &&
	    (trig->chan != SENSOR_CHAN_ROTATION)) {
		return -ENOTSUP;
	}

	key = irq_lock();
	data->data_ready_handler = handler;
	irq_unlock(key);

	return 0;
}

static void qdec_nrfx_event_handler(nrfx_qdec_event_t event)
{
	sensor_trigger_handler_t handler;
	unsigned int key;

	switch (event.type) {
	case NRF_QDEC_EVENT_REPORTRDY:
		accumulate(&qdec_nrfx_data, event.data.report.acc);

		key = irq_lock();
		handler = qdec_nrfx_data.data_ready_handler;
		irq_unlock(key);

		if (handler) {
			struct sensor_trigger trig = {
				.type = SENSOR_TRIG_DATA_READY,
				.chan = SENSOR_CHAN_ROTATION,
			};

			handler(DEVICE_GET(qdec_nrfx), &trig);
		}
		break;

	default:
		LOG_ERR("unhandled event (0x%x)", event.type);
		break;
	}
}

static void qdec_nrfx_gpio_ctrl(bool enable)
{
#if defined(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN)
	uint32_t val = (enable)?(0):(1);

	nrf_gpio_pin_write(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN, val);
	nrf_gpio_cfg_output(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN);
#endif
}

static int qdec_nrfx_init(struct device *dev)
{
	static const nrfx_qdec_config_t config = {
		.reportper          = NRF_QDEC_REPORTPER_40,
		.sampleper          = NRF_QDEC_SAMPLEPER_2048us,
		.psela              = DT_NORDIC_NRF_QDEC_QDEC_0_A_PIN,
		.pselb              = DT_NORDIC_NRF_QDEC_QDEC_0_B_PIN,
#if defined(DT_NORDIC_NRF_QDEC_QDEC_0_LED_PIN)
		.pselled            = DT_NORDIC_NRF_QDEC_QDEC_0_LED_PIN,
#else
		.pselled            = 0xFFFFFFFF, /* disabled */
#endif
		.ledpre             = DT_NORDIC_NRF_QDEC_QDEC_0_LED_PRE,
		.ledpol             = NRF_QDEC_LEPOL_ACTIVE_HIGH,
		.interrupt_priority = NRFX_QDEC_CONFIG_IRQ_PRIORITY,
		.dbfen              = 0, /* disabled */
		.sample_inten       = 0, /* disabled */
	};

	nrfx_err_t nerr;

	LOG_DBG("");

	IRQ_CONNECT(DT_NORDIC_NRF_QDEC_QDEC_0_IRQ,
		    DT_NORDIC_NRF_QDEC_QDEC_0_IRQ_PRIORITY,
		    nrfx_isr, nrfx_qdec_irq_handler, 0);

	nerr = nrfx_qdec_init(&config, qdec_nrfx_event_handler);
	if (nerr == NRFX_ERROR_INVALID_STATE) {
		LOG_ERR("qdec already in use");
		return -EBUSY;
	} else if (nerr != NRFX_SUCCESS) {
		LOG_ERR("failed to initialize qdec");<commit_msg>drivers: sensor: Update DT symbols in qdec_nrfx driver<commit_after>/*
 * Copyright (c) 2018, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <sensor.h>

#include <nrfx_qdec.h>
#include <hal/nrf_gpio.h>

#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(qdec_nrfx);


#define FULL_ANGLE 360

/* limit range to avoid overflow when converting steps to degrees */
#define ACC_MAX (INT_MAX / FULL_ANGLE)
#define ACC_MIN (INT_MIN / FULL_ANGLE)


struct qdec_nrfx_data {
	s32_t                    acc;
	sensor_trigger_handler_t data_ready_handler;
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	u32_t                    pm_state;
#endif
};


static struct qdec_nrfx_data qdec_nrfx_data;

DEVICE_DECLARE(qdec_nrfx);


static void accumulate(struct qdec_nrfx_data *data, int16_t acc)
{
	unsigned int key = irq_lock();

	bool overflow = ((acc > 0) && (ACC_MAX - acc < data->acc)) ||
			((acc < 0) && (ACC_MIN - acc > data->acc));

	if (!overflow) {
		data->acc += acc;
	}

	irq_unlock(key);
}

static int qdec_nrfx_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;

	int16_t acc;
	int16_t accdbl;

	ARG_UNUSED(dev);

	LOG_DBG("");

	if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_ROTATION)) {
		return -ENOTSUP;
	}

	nrfx_qdec_accumulators_read(&acc, &accdbl);

	accumulate(data, acc);

	return 0;
}

static int qdec_nrfx_channel_get(struct device       *dev,
				 enum sensor_channel  chan,
				 struct sensor_value *val)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;
	unsigned int key;
	s32_t acc;

	ARG_UNUSED(dev);
	LOG_DBG("");

	if (chan != SENSOR_CHAN_ROTATION) {
		return -ENOTSUP;
	}

	key = <KEY>();
	acc = data->acc;
	data->acc = 0;
	irq_unlock(key);

	BUILD_ASSERT_MSG(DT_NORDIC_NRF_QDEC_QDEC_0_STEPS > 0,
			 "only positive number valid");
	BUILD_ASSERT_MSG(DT_NORDIC_NRF_QDEC_QDEC_0_STEPS <= 2148,
			 "overflow possible");

	val->val1 = (acc * FULL_ANGLE) / DT_NORDIC_NRF_QDEC_QDEC_0_STEPS;
	val->val2 = (acc * FULL_ANGLE)
		    - (val->val1 * DT_NORDIC_NRF_QDEC_QDEC_0_STEPS);
	if (val->val2 != 0) {
		val->val2 *= 1000000;
		val->val2 /= DT_NORDIC_NRF_QDEC_QDEC_0_STEPS;
	}

	return 0;
}

static int qdec_nrfx_trigger_set(struct device               *dev,
				 const struct sensor_trigger *trig,
				 sensor_trigger_handler_t     handler)
{
	struct qdec_nrfx_data *data = &qdec_nrfx_data;
	unsigned int key;

	ARG_UNUSED(dev);
	LOG_DBG("");

	if (trig->type != SENSOR_TRIG_DATA_READY) {
		return -ENOTSUP;
	}

	if ((trig->chan != SENSOR_CHAN_ALL) &&
	    (trig->chan != SENSOR_CHAN_ROTATION)) {
		return -ENOTSUP;
	}

	key = irq_lock();
	data->data_ready_handler = handler;
	irq_unlock(key);

	return 0;
}

static void qdec_nrfx_event_handler(nrfx_qdec_event_t event)
{
	sensor_trigger_handler_t handler;
	unsigned int key;

	switch (event.type) {
	case NRF_QDEC_EVENT_REPORTRDY:
		accumulate(&qdec_nrfx_data, event.data.report.acc);

		key = irq_lock();
		handler = qdec_nrfx_data.data_ready_handler;
		irq_unlock(key);

		if (handler) {
			struct sensor_trigger trig = {
				.type = SENSOR_TRIG_DATA_READY,
				.chan = SENSOR_CHAN_ROTATION,
			};

			handler(DEVICE_GET(qdec_nrfx), &trig);
		}
		break;

	default:
		LOG_ERR("unhandled event (0x%x)", event.type);
		break;
	}
}

static void qdec_nrfx_gpio_ctrl(bool enable)
{
#if defined(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN)
	uint32_t val = (enable)?(0):(1);

	nrf_gpio_pin_write(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN, val);
	nrf_gpio_cfg_output(DT_NORDIC_NRF_QDEC_QDEC_0_ENABLE_PIN);
#endif
}

static int qdec_nrfx_init(struct device *dev)
{
	static const nrfx_qdec_config_t config = {
		.reportper          = NRF_QDEC_REPORTPER_40,
		.sampleper          = NRF_QDEC_SAMPLEPER_2048us,
		.psela              = DT_NORDIC_NRF_QDEC_QDEC_0_A_PIN,
		.pselb              = DT_NORDIC_NRF_QDEC_QDEC_0_B_PIN,
#if defined(DT_NORDIC_NRF_QDEC_QDEC_0_LED_PIN)
		.pselled            = DT_NORDIC_NRF_QDEC_QDEC_0_LED_PIN,
#else
		.pselled            = 0xFFFFFFFF, /* disabled */
#endif
		.ledpre             = DT_NORDIC_NRF_QDEC_QDEC_0_LED_PRE,
		.ledpol             = NRF_QDEC_LEPOL_ACTIVE_HIGH,
		.interrupt_priority = NRFX_QDEC_CONFIG_IRQ_PRIORITY,
		.dbfen              = 0, /* disabled */
		.sample_inten       = 0, /* disabled */
	};

	nrfx_err_t nerr;

	LOG_DBG("");

	IRQ_CONNECT(DT_NORDIC_NRF_QDEC_QDEC_0_IRQ_0,
		    DT_NORDIC_NRF_QDEC_QDEC_0_IRQ_0_PRIORITY,
		    nrfx_isr, nrfx_qdec_irq_handler, 0);

	nerr = nrfx_qdec_init(&config, qdec_nrfx_event_handler);
	if (nerr == NRFX_ERROR_INVALID_STATE) {
		LOG_ERR("qdec already in use");
		return -EBUSY;
	} else if (nerr != NRFX_SUCCESS) {
		LOG_ERR("failed to initialize qdec");
{'fraction_non_alphanumeric': 0.11063739074824132, 'fraction_numerical': 0.0164144105734385, 'mean_word_length': 3.996272630457934, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1064238', 'n_tokens_mistral': 4247, 'n_tokens_neox': 3999, 'n_words': 676}