/*
 * Copyright (c) 2018 Alexander Wachter
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <kernel.h>
#include <misc/printk.h>
#include <device.h>
#include <can.h>
#include <gpio.h>

#define TX_THREAD_STACK_SIZE 512
#define LED_THREAD_STACK_SIZE 512
#define RX_STR_THREAD_STACK_SIZE 512
#define TX_THREAD_PRIORITY 2
#define LED_MSG_ID (0x10)
#define BUTTON_MSG_ID (0x01)
#define STR_MSG_ID (0x12345)

#define SET_LED 0
#define RESET_LED 1


#define NUM_LEDS_STR STRINGIFY(NUM_LEDS)

K_THREAD_STACK_DEFINE(tx_thread_stack, TX_THREAD_STACK_SIZE);
K_THREAD_STACK_DEFINE(led_thread_stack, LED_THREAD_STACK_SIZE);
K_THREAD_STACK_DEFINE(rx_str_thread_stack, RX_STR_THREAD_STACK_SIZE);
struct k_thread tx_thread_data;
struct k_thread led_thread_data;
struct k_thread rx_str_thread_data;
struct k_sem tx_sem;
static struct gpio_callback gpio_cb;
CAN_DEFINE_MSGQ(led_msgq, 2);
CAN_DEFINE_MSGQ(str_msgq, 5);

void tx_irq_callback(u32_t error_flags)
{
	if (error_flags) {
		printk("Callback! error-code: %d\n", error_flags);
	}
}

void button_callback(struct device *port,
		     struct gpio_callback *cb, u32_t pins)
{
	k_sem_give(&tx_sem);
}

void send_string(char *string, struct device *can_dev)
{
	struct can_msg msg;
	int str_len;

	msg.ext_id = STR_MSG_ID;
	msg.id_type = CAN_EXTENDED_IDENTIFIER;
	msg.dlc = 0;
	msg.rtr = CAN_DATAFRAME;

	for (str_len = strlen(string); str_len; ) {
		msg.dlc = str_len >= 8 ? 8 : str_len;
		str_len -= msg.dlc;
		memcpy(msg.data, string, msg.dlc);
		string += msg.dlc;
		can_send(can_dev, &msg, 10, tx_irq_callback);
	}
}

void tx_thread(void *can_dev_param, void *unused2, void *unused3)
{
	u8_t toggle = SET_LED;
	u16_t button_press_cnt = 0U;
	struct can_msg msg;
	struct can_msg msg_button_cnt;
	struct device *can_dev = can_dev_param;

	msg.std_id = LED_MSG_ID;
	msg.id_type = CAN_STANDARD_IDENTIFIER;
	msg.dlc = 1;
	msg.rtr = CAN_DATAFRAME;
	msg.data[0] = 0;

	msg_button_cnt.std_id = BUTTON_MSG_ID;
	msg_button_cnt.id_type = CAN_STANDARD_IDENTIFIER;
	msg_button_cnt.dlc = 2;
	msg_button_cnt.rtr = CAN_DATAFRAME;
	msg_button_cnt.data[0] = 0;
	msg_button_cnt.data[1] = 0;

	printk("TX thread is running.\n");
	while (1) {
		k_sem_take(&tx_sem, K_FOREVER);
		button_press_cnt++;
		toggle = (toggle == SET_LED) ? RESET_LED : SET_LED;
		printk("Button pressed! Send message %u\n", toggle);
		msg.data[0] = toggle;
		msg_button_cnt.data[0] = button_press_cnt & 0xFF;
		msg_button_cnt.data[1] = (button_press_cnt >> 8) & 0xFF;
		can_send(can_dev, &msg, 10, tx_irq_callback);
		can_send(can_dev, &msg_button_cnt, 10, NULL);
		if (toggle == SET_LED) {
			send_string("String sent over CAN\n", can_dev);
		}
	}
}

void rx_str_thread(void *msgq, void *can_dev_param, void *unused)
{
	struct can_msg msg;
	const struct can_filter filter = {
		.id_type = CAN_EXTENDED_IDENTIFIER,
		.rtr = CAN_DATAFRAME,
		.ext_id = STR_MSG_ID,
		.rtr_mask = 1,
		.ext_id_mask = CAN_EXT_ID_MASK
	};
	struct device *can_dev = can_dev_param;

	can_attach_msgq(can_dev, msgq, &filter);

	while (1) {
		k_msgq_get((struct k_msgq *)msgq, &msg, K_FOREVER);
		for (int i = 0; i < msg.dlc; i++)
			printk("%c", msg.data[i]);
	}
}

void led_thread(void *msgq, void *can_dev_param, void *gpio_dev_param)
{
	const struct can_filter filter = {
		.id_type = CAN_STANDARD_IDENTIFIER,
		.rtr = CAN_DATAFRAME,
		.std_id = LED_MSG_ID,
		.rtr_mask = 1,
		.std_id_mask = CAN_STD_ID_MASK
	};
	struct device *can_dev = can_dev_param;
	struct device *gpio_dev = gpio_dev_param;
	struct can_msg msg;
	int ret;
	int filter_id;

	ret = gpio_pin_configure(gpio_dev, CONFIG_PIN_LED_1, GPIO_DIR_OUT);
	gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0);

	if (ret) {
		printk("ERROR configure pins\n");
		return;
	}

	filter_id = can_attach_msgq(can_dev, msgq, &filter);
	printk("filter id: %d\n", filter_id);

	while (1) {
		k_msgq_get((struct k_msgq *)msgq, &msg, K_FOREVER);

		if (msg.dlc != 1) {
			continue;
		}

		switch (msg.data[0]) {
		case SET_LED:
			gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 1);

			break;
		case RESET_LED:
			gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0);
			break;
		}
	}
}

void rx_button_isr(struct can_msg *msg)
{
	u16_t cnt = msg->data[0] | (msg->data[1] << 8);

	printk("Button pressed %d times\n", cnt);
}

void main(void)
{
	const struct can_filter filter = {
		.id_type = CAN_STANDARD_IDENTIFIER,
		.rtr = CAN_DATAFRAME,
		.std_id = BUTTON_MSG_ID,
		.rtr_mask = 1,
		.std_id_mask = CAN_STD_ID_MASK
	};
	struct device *can_dev, *led_gpio_dev, *button_gpio_dev;
	int ret;

	can_dev = device_get_binding(CONFIG_CAN_DEV);
	if (!can_dev) {
		printk("CAN: Device driver not found.\n");
		return;
	}

#ifdef CONFIG_LOOPBACK_MODE
	can_configure(can_dev, CAN_LOOPBACK_MODE, 250000);
#endif

	led_gpio_dev = device_get_binding(CONFIG_GPIO_LED_DEV);
	if (!led_gpio_dev) {
		printk("LED: Device driver not found.\n");
		return;
	}

	k_sem_init(&tx_sem, 0, INT_MAX);

	button_gpio_dev = device_get_binding(CONFIG_GPIO_BUTTON_DEV);
	if (!button_gpio_dev) {
		printk("Button: Device driver not found.\n");
		return;
	}

	ret = gpio_pin_configure(button_gpio_dev, CONFIG_PIN_USER_BUTTON,
				    (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
				     GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE));
	if (ret) {
		printk("Error configuring  button pin\n");
	}

	gpio_init_callback(&gpio_cb, button_callback,
			   BIT(CONFIG_PIN_USER_BUTTON));

	ret = gpio_add_callback(button_gpio_dev, &gpio_cb);
	if (ret) {
		printk("Cannot setup callback!\n");
	}

	ret = gpio_pin_enable_callback(button_gpio_dev, CONFIG_PIN_USER_BUTTON);
	if (ret) {
		printk("Error enabling callback!\n");
	}

	can_attach_isr(can_dev, rx_button_isr, &filter);

	k_tid_t tx_tid = k_thread_create(&tx_thread_data, tx_thread_stack,
					 K_THREAD_STACK_SIZEOF(tx_thread_stack),
					 tx_thread,
					 can_dev, NULL, NULL,
					 TX_THREAD_PRIORITY, 0, K_NO_WAIT);
	if (!tx_tid) {
		printk("ERROR spawning tx_thread\n");
	}

	k_tid_t led_tid = k_thread_create(&led_thread_data, led_thread_stack,
					  K_THREAD_STACK_SIZEOF(led_thread_stack),
					  led_thread,
					  &led_msgq, can_dev, led_gpio_dev,
					  TX_THREAD_PRIORITY, 0, K_NO_WAIT);
	if (!led_tid) {
		printk("ERROR spawning led_thread\n");
	}

	k_tid_t str_tid = k_thread_create(&rx_str_thread_data,
					  rx_str_thread_stack,
					  K_THREAD_STACK_SIZEOF(rx_str_thread_stack),
					  rx_str_thread,
					  &str_msgq, can_dev, NULL,
					  TX_THREAD_PRIORITY, 0, K_NO_WAIT);
	if (!str_tid) {
		printk("ERROR spawning str_thread\n");
	}

	printk("Finished init. waiting for Interrupts\n");
}
