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

#include <drivers/led_strip.h>

#include <string.h>

#define LOG_LEVEL CONFIG_LED_STRIP_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(ws2812b_sw);

#include <zephyr.h>
#include <soc.h>
#include <drivers/gpio.h>
#include <device.h>
#include <drivers/clock_control.h>

#define BLOCKING ((void *)1)

static int send_buf(u8_t *buf, size_t len)
{
	/* Address of OUTSET. OUTCLR is OUTSET + 4 */
	volatile u32_t *base = (u32_t *)(NRF_GPIO_BASE + 0x508);
	u32_t pin = BIT(CONFIG_WS2812B_SW_GPIO_PIN);
	struct device *clock;
	unsigned int key;
	/* Initilization of i is strictly not needed, but it avoids an
	 * uninitialized warning with the inline assembly.
	 */
	u32_t i = 0U;

	clock = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL "_16M");
	if (!clock) {
		LOG_ERR("Unable to get HF clock");
		return -EIO;
	}

	/* The inline assembly further below is designed to work only with
	 * the 16 MHz clock enabled.
	 */
	clock_control_on(clock, BLOCKING);
	key = irq_lock();

	while (len--) {
		u32_t b = *buf++;

		/* Generate signal out of the bits, MSB. 1-bit should be
		 * roughly 0.85us high, 0.4us low, whereas a 0-bit should be
		 * roughly 0.4us high, 0.85us low.
		 */
		__asm volatile ("movs %[i], #8\n" /* i = 8 */
				".start_bit:\n"

				/* OUTSET = BIT(LED_PIN) */
				"strb %[p], [%[r], #0]\n"

				/* if (b & 0x80) goto .long */
				"tst %[b], %[m]\n"
				"bne .long\n"

				/* 0-bit */
				"nop\nnop\n"
				/* OUTCLR = BIT(LED_PIN) */
				"strb %[p], [%[r], #4]\n"
				"nop\nnop\nnop\n"
				"b .next_bit\n"

				/* 1-bit */
				".long:\n"
				"nop\nnop\nnop\nnop\nnop\nnop\nnop\n"
				/* OUTCLR = BIT(LED_PIN) */
				"strb %[p], [%[r], #4]\n"

				".next_bit:\n"
				/* b <<= 1 */
				"lsl %[b], #1\n"
				/* i-- */
				"sub %[i], #1\n"
				/* if (i > 0) goto .start_bit */
				"bne .start_bit\n"
				:
				[i] "+r" (i)
				:
				[b] "l" (b),
				[m] "l" (0x80),
				[r] "l" (base),
				[p] "r" (pin)
				:);
	}

	irq_unlock(key);
	clock_control_off(clock, NULL);

	return 0;
}

static int ws2812b_sw_update_rgb(struct device *dev, struct led_rgb *pixels,
				 size_t num_pixels)
{
	u8_t *ptr = (u8_t *)pixels;
	size_t i;

	/* Convert from RGB to GRB format */
	for (i = 0; i < num_pixels; i++) {
		u8_t r = pixels[i].r;
		u8_t b = pixels[i].b;
		u8_t g = pixels[i].g;

		*ptr++ = g;
		*ptr++ = r;
		*ptr++ = b;
	}

	return send_buf((u8_t *)pixels, num_pixels * 3);
}

static int ws2812b_sw_update_channels(struct device *dev, u8_t *channels,
				      size_t num_channels)
{
	LOG_ERR("update_channels not implemented");
	return -ENOSYS;
}

static int ws2812b_sw_init(struct device *dev)
{
	struct device *gpio;

	gpio = device_get_binding(CONFIG_WS2812B_SW_GPIO_NAME);
	if (!gpio) {
		LOG_ERR("Unable to find %s", CONFIG_WS2812B_SW_GPIO_NAME);
		return -ENODEV;
	}

	gpio_pin_configure(gpio, CONFIG_WS2812B_SW_GPIO_PIN, GPIO_DIR_OUT);

	return 0;
}

static const struct led_strip_driver_api ws2812b_sw_api = {
	.update_rgb = ws2812b_sw_update_rgb,
	.update_channels = ws2812b_sw_update_channels,
};

DEVICE_AND_API_INIT(ws2812b_sw, CONFIG_WS2812B_SW_NAME, ws2812b_sw_init, NULL,
		    NULL, POST_KERNEL, CONFIG_LED_STRIP_INIT_PRIORITY,
		    &ws2812b_sw_api);
