/*
 * Copyright (c) 2021, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/display.h>
#include <string.h>

#define PIXEL_BIT(idx, val)  (val ? BIT(idx) : 0)
#define PIXEL_MASK(...)      (FOR_EACH_IDX(PIXEL_BIT, (|), __VA_ARGS__))

static struct display_capabilities caps;
static uint8_t buf[5];
static const struct display_buffer_descriptor buf_desc = {
	.buf_size = sizeof(buf),
	.width    = 5,
	.height   = 5,
	.pitch    = 8,
};

static void update_block_3x3(const struct device *dev)
{
	int ret;
	static const uint8_t small_bufs[][2] = {
		{ PIXEL_MASK(0, 1, 0) |
		  PIXEL_MASK(0, 1, 0) << 4,
		  PIXEL_MASK(0, 1, 0) },
		{ PIXEL_MASK(0, 0, 1) |
		  PIXEL_MASK(0, 1, 0) << 4,
		  PIXEL_MASK(1, 0, 0) },
		{ PIXEL_MASK(0, 0, 0) |
		  PIXEL_MASK(1, 1, 1) << 4,
		  PIXEL_MASK(0, 0, 0) },
		{ PIXEL_MASK(1, 0, 0) |
		  PIXEL_MASK(0, 1, 0) << 4,
		  PIXEL_MASK(0, 0, 1) },
	};
	static const struct display_buffer_descriptor small_buf_desc = {
		.buf_size = sizeof(small_bufs[0]),
		.width    = 3,
		.height   = 3,
		.pitch    = 4,
	};

	for (int i = 0; i < 4 * ARRAY_SIZE(small_bufs); ++i) {
		k_sleep(K_MSEC(100));

		ret = display_write(dev, 1, 1,
				    &small_buf_desc, small_bufs[i % 4]);
		if (ret < 0) {
			printk("display_write failed: %u/%d\n",
				__LINE__, ret);
		}
	}
}

static void update_block_5x5(const struct device *dev)
{
	int ret;

	buf[0] = PIXEL_MASK(0, 0, 0, 0, 1);
	buf[1] = PIXEL_MASK(0, 0, 0, 1, 1);
	buf[2] = PIXEL_MASK(0, 0, 1, 1, 1);
	buf[3] = PIXEL_MASK(0, 1, 1, 1, 1);
	buf[4] = PIXEL_MASK(1, 1, 1, 1, 1);
	ret = display_write(dev, 0, 0, &buf_desc, buf);
	if (ret < 0) {
		printk("display_write failed: %u/%d\n",
			__LINE__, ret);
	}

	for (int i = 0; i < 4 * 5; ++i) {
		uint8_t tmp;

		k_sleep(K_MSEC(100));

		tmp = buf[0];
		buf[0] = buf[1];
		buf[1] = buf[2];
		buf[2] = buf[3];
		buf[3] = buf[4];
		buf[4] = tmp;
		ret = display_write(dev, 0, 0, &buf_desc, buf);
		if (ret < 0) {
			printk("display_write failed: %u/%d\n",
				__LINE__, ret);
		}
	}
}

static void show_all_brightness_levels(const struct device *dev)
{
	int ret;
	uint8_t brightness = 0;

	do {
		--brightness;
		ret = display_set_brightness(dev, brightness);
		if (ret < 0) {
			printk("display_set_brightness failed: %u/%d\n",
				__LINE__, ret);
		}

		k_sleep(K_MSEC(5));
	} while (brightness);
}

static void update_through_framebuffer(const struct device *dev)
{
	uint8_t *framebuf = display_get_framebuffer(dev);
	uint8_t dimmed = 0;
	bool inc = false;
	enum {
		MIN_BRIGHTNESS = 0x0F,
		BLOCK_SIZE     = 5,
		STEPS          = BLOCK_SIZE - 1,
		RUNS           = 4
	};

	if (!framebuf) {
		printk("frame buffer not available\n");
		return;
	}

	/* Clear screen. */
	memset(framebuf, 0, caps.x_resolution * caps.y_resolution);

	for (int i = 0; i < 1 + 3 * RUNS * STEPS; ++i) {
		k_sleep(K_MSEC(100));

		for (uint8_t column = 0; column < BLOCK_SIZE; ++column) {
			for (uint8_t row = 0; row < BLOCK_SIZE; ++row) {
				uint8_t diff;
				uint8_t step = (0xFF - MIN_BRIGHTNESS) / STEPS;

				/*
				 * Depending on the iteration, use different
				 * pixel values for:
				 * - vertical lines
				 */
				if (i < 1 * RUNS * STEPS) {
					diff = dimmed > column
					     ? dimmed - column
					     : column - dimmed;
				/*
				 * - horizontal lines
				 */
				} else if (i < 2 * RUNS * STEPS) {
					diff = dimmed > row
					     ? dimmed - row
					     : row - dimmed;
				/*
				 * - diagonal lines
				 */
				} else {
					uint8_t dist = column + row;

					diff = 2 * dimmed > dist
					     ? 2 * dimmed - dist
					     : dist - 2 * dimmed;
					step /= 2;
				}

				framebuf[column + row * caps.x_resolution] =
					MIN_BRIGHTNESS + diff * step;
			}
		}

		if (dimmed == 0 || dimmed == STEPS) {
			inc = !inc;
		}
		if (inc) {
			++dimmed;
		} else {
			--dimmed;
		}
	}
}

void main(void)
{
	printk("nRF LED matrix sample on %s\n", CONFIG_BOARD);

	int ret;
	const struct device *const dev = DEVICE_DT_GET_ONE(nordic_nrf_led_matrix);

	if (!dev) {
		printk("Display device not ready\n");
		return;
	}

	display_get_capabilities(dev, &caps);
	if (!(caps.supported_pixel_formats & PIXEL_FORMAT_MONO01)) {
		printk("Expected pixel format not supported\n");
		return;
	}

	ret = display_set_pixel_format(dev, PIXEL_FORMAT_MONO01);
	if (ret < 0) {
		printk("display_set_pixel_format failed: %u/%d\n",
			__LINE__, ret);
	}

	printk("Started\n");

	for (;;) {
		ret = display_set_brightness(dev, 0x7F);
		if (ret < 0) {
			printk("display_set_brightness failed: %u/%d\n",
				__LINE__, ret);
		}

		buf[0] = PIXEL_MASK(1, 0, 1, 0, 1);
		buf[1] = PIXEL_MASK(1, 1, 0, 0, 1);
		buf[2] = PIXEL_MASK(1, 0, 1, 0, 1);
		buf[3] = PIXEL_MASK(1, 0, 0, 1, 1);
		buf[4] = PIXEL_MASK(1, 0, 1, 0, 1);
		ret = display_write(dev, 0, 0, &buf_desc, buf);
		if (ret < 0) {
			printk("display_write failed: %u/%d\n",
				__LINE__, ret);
		}

		ret = display_blanking_off(dev);
		if (ret < 0) {
			printk("display_blanking_off failed: %u/%d\n",
				__LINE__, ret);
		}

		k_sleep(K_MSEC(500));

		update_block_3x3(dev);

		k_sleep(K_MSEC(500));

		update_block_5x5(dev);

		k_sleep(K_MSEC(200));

		ret = display_blanking_on(dev);
		if (ret < 0) {
			printk("display_blanking_on failed: %u/%d\n",
				__LINE__, ret);
		}

		k_sleep(K_MSEC(500));

		ret = display_blanking_off(dev);
		if (ret < 0) {
			printk("display_blanking_off failed: %u/%d\n",
				__LINE__, ret);
		}

		k_sleep(K_MSEC(500));

		show_all_brightness_levels(dev);

		update_through_framebuffer(dev);

		k_sleep(K_MSEC(500));
	}
}
