/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @addtogroup t_gpio_basic_api
 * @{
 * @defgroup t_gpio_callback_trigger test_gpio_callback_trigger
 * @brief TestPurpose: verify zephyr gpio callback triggered
 * under different INT modes
 * @}
 */

#include "test_gpio.h"

static struct drv_data data;
static int cb_cnt;

static int pin_num(u32_t pins)
{
	int ret = 0;

	while (pins >>= 1) {
		ret++;
	}
	return ret;
}

static void callback(struct device *dev,
		     struct gpio_callback *gpio_cb, u32_t pins)
{
	/*= checkpoint: pins should be marked with correct pin number bit =*/
	zassert_true(pin_num(pins) == PIN_IN, NULL);
	TC_PRINT("callback triggered: %d\n", ++cb_cnt);
	if (cb_cnt >= MAX_INT_CNT) {
		struct drv_data *drv_data = CONTAINER_OF(gpio_cb,
							 struct drv_data, gpio_cb);
		gpio_pin_write(dev, PIN_OUT,
			       (drv_data->mode & GPIO_INT_ACTIVE_HIGH) ? 0 : 1);
		gpio_pin_configure(dev, PIN_IN, GPIO_DIR_IN);
	}
}

static int test_callback(int mode)
{
	struct device *dev = device_get_binding(DEV_NAME);

	gpio_pin_disable_callback(dev, PIN_IN);
	gpio_pin_disable_callback(dev, PIN_OUT);

	/* 1. set PIN_OUT to initial state */
	if (gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT) != 0) {
		TC_ERROR("PIN_OUT config fail\n");
		return TC_FAIL;
	}
	if (gpio_pin_write(dev, PIN_OUT,
			   (mode & GPIO_INT_ACTIVE_HIGH) ? 0 : 1) != 0) {
		TC_ERROR("set PIN_OUT init voltage fail\n");
		return TC_FAIL;
	}

	/* 2. configure PIN_IN callback and trigger condition */
	if (gpio_pin_configure(dev, PIN_IN,
			       GPIO_DIR_IN | GPIO_INT | mode | GPIO_INT_DEBOUNCE) != 0) {
		TC_ERROR("config PIN_IN fail");
		goto err_exit;
	}

	struct drv_data *drv_data = &data;

	drv_data->mode = mode;
	gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
	if (gpio_add_callback(dev, &drv_data->gpio_cb) != 0) {
		TC_ERROR("set PIN_IN callback fail\n");
		return TC_FAIL;
	}

	/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
	cb_cnt = 0;
	gpio_pin_enable_callback(dev, PIN_IN);
	k_sleep(100);
	gpio_pin_write(dev, PIN_OUT, (mode & GPIO_INT_ACTIVE_HIGH) ? 1 : 0);
	k_sleep(1000);

	/*= checkpoint: check callback is triggered =*/
	TC_PRINT("check enabled callback\n");
	if ((mode & GPIO_INT_EDGE) == GPIO_INT_EDGE) {
		if (cb_cnt != 1) {
			TC_ERROR("not trigger callback correctly\n");
			goto err_exit;
		}
		goto pass_exit;
	}

	if ((mode & GPIO_INT_LEVEL) == GPIO_INT_LEVEL) {
		if (cb_cnt != MAX_INT_CNT) {
			TC_ERROR("not trigger callback correctly\n");
			goto err_exit;
		}
	}

pass_exit:
	gpio_remove_callback(dev, &drv_data->gpio_cb);
	return TC_PASS;

err_exit:
	gpio_remove_callback(dev, &drv_data->gpio_cb);
	return TC_FAIL;
}

/* export test cases */
void test_gpio_callback_edge_high(void)
{
	zassert_true(
		test_callback(GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH) == TC_PASS,
		NULL);
}

void test_gpio_callback_edge_low(void)
{
	zassert_true(
		test_callback(GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW) == TC_PASS,
		NULL);
}

void test_gpio_callback_level_high(void)
{
	zassert_true(
		test_callback(GPIO_INT_LEVEL | GPIO_INT_ACTIVE_HIGH) == TC_PASS,
		NULL);
}

void test_gpio_callback_level_low(void)
{
	zassert_true(
		test_callback(GPIO_INT_LEVEL | GPIO_INT_ACTIVE_LOW) == TC_PASS,
		NULL);
}
