/*
 * Copyright (c) 2019 Piotr Mienkowski
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include <limits.h>
#include <sys/util.h>
#include "test_gpio_api.h"

struct gpio_callback gpio_cb;
static int cb_count;

static void callback_edge(const struct device *port, struct gpio_callback *cb,
			  gpio_port_pins_t pins)
{
	zassert_equal(pins, BIT(TEST_PIN),
		     "Detected interrupt on an invalid pin");
	cb_count++;
}

static void callback_level(const struct device *port,
			   struct gpio_callback *cb,
			   gpio_port_pins_t pins)
{
	int ret;

	zassert_equal(pins, BIT(TEST_PIN),
		     "Detected interrupt on an invalid pin");

	ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
	zassert_equal(ret, 0,
		      "Failed to disable pin interrupt in the callback");

	cb_count++;
}

static void pin_set_and_verify(const struct device *port, unsigned int pin,
			       int val,
			       int idx)
{
	zassert_equal(gpio_pin_set(port, pin, val), 0,
		      "Test point %d: failed to set logical pin value", idx);
	k_busy_wait(TEST_GPIO_MAX_RISE_FALL_TIME_US);
}

void test_gpio_pin_interrupt_edge(unsigned int cfg_flags,
				  unsigned int int_flags)
{
	const struct device *port;
	int cb_count_expected;
	unsigned int cfg_out_flag;
	int ret;

	port = device_get_binding(TEST_DEV);
	zassert_not_null(port, "device " TEST_DEV " not found");

	TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);

	ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | GPIO_OUTPUT);
	if (ret == -ENOTSUP) {
		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
		ztest_test_skip();
		return;
	}
	zassert_equal(ret, 0, "Failed to configure the pin");

	if ((cfg_flags & GPIO_ACTIVE_LOW) != 0) {
		cfg_out_flag = GPIO_OUTPUT_HIGH;
	} else {
		cfg_out_flag = GPIO_OUTPUT_LOW;
	}
	ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | cfg_out_flag |
				 cfg_flags);
	zassert_equal(ret, 0, "Failed to configure the pin");

	cb_count = 0;
	cb_count_expected = 0;

	gpio_init_callback(&gpio_cb, callback_edge, BIT(TEST_PIN));
	ret = gpio_add_callback(port, &gpio_cb);

	ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
	if (ret == -ENOTSUP) {
		TC_PRINT("Pin interrupt is not supported.\n");
		ztest_test_skip();
		return;
	}
	zassert_equal(ret, 0, "Failed to configure pin interrupt");

	for (int i = 0; i < 6; i++) {
		pin_set_and_verify(port, TEST_PIN, 1, i);
		if (int_flags & GPIO_INT_HIGH_1) {
			cb_count_expected++;
		}
		zassert_equal(cb_count, cb_count_expected,
			      "Test point %d: Pin interrupt triggered invalid "
			      "number of times on rising/to active edge", i);

		pin_set_and_verify(port, TEST_PIN, 0, i);
		if (int_flags & GPIO_INT_LOW_0) {
			cb_count_expected++;
		}
		zassert_equal(cb_count, cb_count_expected,
			      "Test point %d: Pin interrupt triggered invalid "
			      "number of times on falling/to inactive edge", i);
	}

	ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
	zassert_equal(ret, 0, "Failed to disable pin interrupt");

	for (int i = 0; i < 6; i++) {
		pin_set_and_verify(port, TEST_PIN, 1, i);
		pin_set_and_verify(port, TEST_PIN, 0, i);
		zassert_equal(cb_count, cb_count_expected,
			      "Pin interrupt triggered when disabled");
	}
}

void test_gpio_pin_interrupt_level(unsigned int cfg_flags,
				   unsigned int int_flags)
{
	const struct device *port;
	int cb_count_expected;
	unsigned int cfg_out_flag;
	int pin_out_val;
	int ret;

	port = device_get_binding(TEST_DEV);
	zassert_not_null(port, "device " TEST_DEV " not found");

	TC_PRINT("Running test on port=%s, pin=%d\n", TEST_DEV, TEST_PIN);

	ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | GPIO_OUTPUT);
	if (ret == -ENOTSUP) {
		TC_PRINT("Simultaneous pin in/out mode is not supported.\n");
		ztest_test_skip();
		return;
	}
	zassert_equal(ret, 0, "Failed to configure the pin");

	pin_out_val = ((int_flags & GPIO_INT_HIGH_1) != 0) ? 0 : 1;

	if ((cfg_flags & GPIO_ACTIVE_LOW) != 0) {
		cfg_out_flag = (pin_out_val != 0) ? GPIO_OUTPUT_LOW :
						    GPIO_OUTPUT_HIGH;
	} else {
		cfg_out_flag = (pin_out_val != 0) ? GPIO_OUTPUT_HIGH :
						    GPIO_OUTPUT_LOW;
	}

	ret = gpio_pin_configure(port, TEST_PIN, GPIO_INPUT | cfg_out_flag |
				 cfg_flags);
	zassert_equal(ret, 0, "Failed to configure the pin");

	cb_count = 0;
	cb_count_expected = 0;

	gpio_init_callback(&gpio_cb, callback_level, BIT(TEST_PIN));
	ret = gpio_add_callback(port, &gpio_cb);

	ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
	if (ret == -ENOTSUP) {
		TC_PRINT("Pin interrupt is not supported.\n");
		ztest_test_skip();
		return;
	}
	zassert_equal(ret, 0, "Failed to configure pin interrupt");

	zassert_equal(cb_count, cb_count_expected,
		      "Pin interrupt triggered on level %d", pin_out_val);

	for (int i = 0; i < 6; i++) {
		pin_out_val = (pin_out_val != 0) ? 0 : 1;
		pin_set_and_verify(port, TEST_PIN, pin_out_val, i);
		cb_count_expected++;
		zassert_equal(cb_count, cb_count_expected,
			      "Test point %d: Pin interrupt triggered invalid "
			      "number of times on level %d", i, pin_out_val);

		pin_out_val = (pin_out_val != 0) ? 0 : 1;
		pin_set_and_verify(port, TEST_PIN, pin_out_val, i);
		zassert_equal(cb_count, cb_count_expected,
			      "Test point %d: Pin interrupt triggered invalid "
			      "number of times on level %d", i, pin_out_val);

		/* Re-enable pin level interrupt */
		ret = gpio_pin_interrupt_configure(port, TEST_PIN, int_flags);
		zassert_equal(ret, 0,
			      "Failed to re-enable pin level interrupt");
	}

	ret = gpio_pin_interrupt_configure(port, TEST_PIN, GPIO_INT_DISABLE);
	zassert_equal(ret, 0, "Failed to disable pin interrupt");

	for (int i = 0; i < 6; i++) {
		pin_set_and_verify(port, TEST_PIN, 1, i);
		pin_set_and_verify(port, TEST_PIN, 0, i);
		zassert_equal(cb_count, cb_count_expected,
			      "Pin interrupt triggered when disabled");
	}
}

/** @brief Verify GPIO_INT_EDGE_RISING flag. */
void test_gpio_int_edge_rising(void)
{
	test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_RISING);
}

/** @brief Verify GPIO_INT_EDGE_FALLING flag. */
void test_gpio_int_edge_falling(void)
{
	test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_FALLING);
}

/** @brief Verify GPIO_INT_EDGE_BOTH flag. */
void test_gpio_int_edge_both(void)
{
	test_gpio_pin_interrupt_edge(0, GPIO_INT_EDGE_BOTH);
}

/** @brief Verify GPIO_INT_EDGE_TO_ACTIVE flag. */
void test_gpio_int_edge_to_active(void)
{
	TC_PRINT("Step 1: Configure pin as active high\n");
	test_gpio_pin_interrupt_edge(GPIO_ACTIVE_HIGH, GPIO_INT_EDGE_TO_ACTIVE);
	TC_PRINT("Step 2: Configure pin as active low\n");
	test_gpio_pin_interrupt_edge(GPIO_ACTIVE_LOW, GPIO_INT_EDGE_TO_ACTIVE);
}

/** @brief Verify GPIO_INT_EDGE_TO_INACTIVE flag. */
void test_gpio_int_edge_to_inactive(void)
{
	TC_PRINT("Step 1: Configure pin as active high\n");
	test_gpio_pin_interrupt_edge(GPIO_ACTIVE_HIGH, GPIO_INT_EDGE_TO_INACTIVE);
	TC_PRINT("Step 2: Configure pin as active low\n");
	test_gpio_pin_interrupt_edge(GPIO_ACTIVE_LOW, GPIO_INT_EDGE_TO_INACTIVE);
}

/** @brief Verify GPIO_INT_LEVEL_HIGH flag. */
void test_gpio_int_level_high(void)
{
	test_gpio_pin_interrupt_level(0, GPIO_INT_LEVEL_HIGH);
}

/** @brief Verify GPIO_INT_LEVEL_LOW flag. */
void test_gpio_int_level_low(void)
{
	test_gpio_pin_interrupt_level(0, GPIO_INT_LEVEL_LOW);
}

/** @brief Verify GPIO_INT_LEVEL_ACTIVE flag. */
void test_gpio_int_level_active(void)
{
	TC_PRINT("Step 1: Configure pin as active high\n");
	test_gpio_pin_interrupt_level(GPIO_ACTIVE_HIGH, GPIO_INT_LEVEL_ACTIVE);
	TC_PRINT("Step 2: Configure pin as active low\n");
	test_gpio_pin_interrupt_level(GPIO_ACTIVE_LOW, GPIO_INT_LEVEL_ACTIVE);
}

/** @brief Verify GPIO_INT_LEVEL_INACTIVE flag. */
void test_gpio_int_level_inactive(void)
{
	TC_PRINT("Step 1: Configure pin as active high\n");
	test_gpio_pin_interrupt_level(GPIO_ACTIVE_HIGH, GPIO_INT_LEVEL_INACTIVE);
	TC_PRINT("Step 2: Configure pin as active low\n");
	test_gpio_pin_interrupt_level(GPIO_ACTIVE_LOW, GPIO_INT_LEVEL_INACTIVE);
}
