/* microbit.c - BBC micro:bit specific hooks */

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

#include <gpio.h>
#include <board.h>
#include <soc.h>
#include <misc/printk.h>
#include <ctype.h>
#include <flash.h>
#include <gpio.h>
#include <pwm.h>

#include <display/mb_display.h>

#include <bluetooth/mesh.h>

#include "board.h"

#define SCROLL_SPEED   K_MSEC(300)

#define BUZZER_PIN     EXT_P0_GPIO_PIN
#define BEEP_DURATION  K_MSEC(60)

#define SEQ_PER_BIT  976
#define SEQ_PAGE     (NRF_FICR->CODEPAGESIZE * (NRF_FICR->CODESIZE - 1))
#define SEQ_MAX      (NRF_FICR->CODEPAGESIZE * 8 * SEQ_PER_BIT)

static struct device *gpio;
static struct device *nvm;
static struct device *pwm;

static struct k_work button_work;

void board_seq_update(u32_t seq)
{
	u32_t loc, seq_map;
	int err;

	if (seq % SEQ_PER_BIT) {
		return;
	}

	loc = (SEQ_PAGE + ((seq / SEQ_PER_BIT) / 32));

	err = flash_read(nvm, loc, &seq_map, sizeof(seq_map));
	if (err) {
		printk("flash_read err %d\n", err);
		return;
	}

	seq_map >>= 1;

	flash_write_protection_set(nvm, false);
	err = flash_write(nvm, loc, &seq_map, sizeof(seq_map));
	flash_write_protection_set(nvm, true);
	if (err) {
		printk("flash_write err %d\n", err);
	}
}

static u32_t get_seq(void)
{
	u32_t seq_map, seq = 0;
	int err, i;

	for (i = 0; i < NRF_FICR->CODEPAGESIZE / sizeof(seq_map); i++) {
		err = flash_read(nvm, SEQ_PAGE + (i * sizeof(seq_map)),
				 &seq_map, sizeof(seq_map));
		if (err) {
			printk("flash_read err %d\n", err);
			return seq;
		}

		printk("seq_map 0x%08x\n", seq_map);

		if (seq_map) {
			seq = ((i * 32) +
			       (32 - popcount(seq_map))) * SEQ_PER_BIT;
			if (!seq) {
				return 0;
			}

			break;
		}
	}

	seq += SEQ_PER_BIT;
	if (seq >= SEQ_MAX) {
		seq = 0;
	}

	if (seq) {
		seq_map >>= 1;
		flash_write_protection_set(nvm, false);
		err = flash_write(nvm, SEQ_PAGE + (i * sizeof(seq_map)),
				  &seq_map, sizeof(seq_map));
		flash_write_protection_set(nvm, true);
		if (err) {
			printk("flash_write err %d\n", err);
		}
	} else {
		printk("Performing flash erase of page 0x%08x\n", SEQ_PAGE);
		err = flash_erase(nvm, SEQ_PAGE, NRF_FICR->CODEPAGESIZE);
		if (err) {
			printk("flash_erase err %d\n", err);
		}
	}

	return seq;
}

static void button_send_pressed(struct k_work *work)
{
	printk("button_send_pressed()\n");
	board_button_1_pressed();
}

static void button_pressed(struct device *dev, struct gpio_callback *cb,
			   uint32_t pins)
{
	struct mb_display *disp = mb_display_get();

	if (pins & BIT(SW0_GPIO_PIN)) {
		k_work_submit(&button_work);
	} else {
		if (board_toggle_relay()) {
			mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT,
					 SCROLL_SPEED, "R on");
		} else {
			mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT,
					 SCROLL_SPEED, "R off");
		}
	}
}

static const struct {
	char  note;
	u32_t period;
	u32_t sharp;
} period_map[] = {
	{ 'C',  3822,  3608 },
	{ 'D',  3405,  3214 },
	{ 'E',  3034,  3034 },
	{ 'F',  2863,  2703 },
	{ 'G',  2551,  2407 },
	{ 'A',  2273,  2145 },
	{ 'B',  2025,  2025 },
};

static u32_t get_period(char note, bool sharp)
{
	int i;

	if (note == ' ') {
		return 0;
	}

	for (i = 0; i < ARRAY_SIZE(period_map); i++) {
		if (period_map[i].note != note) {
			continue;
		}

		if (sharp) {
			return period_map[i].sharp;
		} else {
			return period_map[i].period;
		}
	}

	return 1500;
}

void board_play_tune(const char *str)
{
	while (*str) {
		u32_t period, duration = 0;

		while (*str && !isdigit(*str)) {
			str++;
		}

		while (isdigit(*str)) {
			duration *= 10;
			duration += *str - '0';
			str++;
		}

		if (!*str) {
			break;
		}

		if (str[1] == '#') {
			period = get_period(*str, true);
			str += 2;
		} else {
			period = get_period(*str, false);
			str++;
		}

		if (period) {
			pwm_pin_set_usec(pwm, BUZZER_PIN, period, period / 2);
		}

		k_sleep(duration);

		/* Disable the PWM */
		pwm_pin_set_usec(pwm, BUZZER_PIN, 0, 0);
	}
}

void board_heartbeat(u8_t hops, u16_t feat)
{
	struct mb_display *disp = mb_display_get();
	const struct mb_image hops_img[] = {
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 }),
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 0, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 }),
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 1, 1, 1, 1 }),
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 1, 1, 1, 1 }),
		MB_IMAGE({ 1, 0, 1, 0, 1 },
			 { 0, 0, 0, 0, 0 },
			 { 1, 0, 0, 0, 1 },
			 { 0, 0, 0, 0, 0 },
			 { 1, 0, 1, 0, 1 })
	};

	printk("%u hops\n", hops);

	if (hops) {
		hops = min(hops, ARRAY_SIZE(hops_img));
		mb_display_image(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(2),
				 &hops_img[hops - 1], 1);
	}
}

void board_other_dev_pressed(u16_t addr)
{
	struct mb_display *disp = mb_display_get();

	printk("board_other_dev_pressed(0x%04x)\n", addr);

	mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(2),
			 "%X", (addr & 0xf));
}

void board_attention(bool attention)
{
	struct mb_display *disp = mb_display_get();
	static const struct mb_image attn_img[] = {
		MB_IMAGE({ 0, 0, 0, 0, 0 },
			 { 0, 0, 0, 0, 0 },
			 { 0, 0, 1, 0, 0 },
			 { 0, 0, 0, 0, 0 },
			 { 0, 0, 0, 0, 0 }),
		MB_IMAGE({ 0, 0, 0, 0, 0 },
			 { 0, 1, 1, 1, 0 },
			 { 0, 1, 1, 1, 0 },
			 { 0, 1, 1, 1, 0 },
			 { 0, 0, 0, 0, 0 }),
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 0, 1, 1 },
			 { 1, 1, 1, 1, 1 },
			 { 1, 1, 1, 1, 1 }),
		MB_IMAGE({ 1, 1, 1, 1, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 0, 0, 0, 1 },
			 { 1, 1, 1, 1, 1 }),
	};

	if (attention) {
		mb_display_image(disp,
				 MB_DISPLAY_MODE_DEFAULT | MB_DISPLAY_FLAG_LOOP,
				 K_MSEC(150), attn_img, ARRAY_SIZE(attn_img));
	} else {
		mb_display_stop(disp);
	}
}

static void configure_button(void)
{
	static struct gpio_callback button_cb;

	k_work_init(&button_work, button_send_pressed);

	gpio = device_get_binding(SW0_GPIO_NAME);

	gpio_pin_configure(gpio, SW0_GPIO_PIN,
			   (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
			    GPIO_INT_ACTIVE_LOW));
	gpio_pin_configure(gpio, SW1_GPIO_PIN,
			   (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
			    GPIO_INT_ACTIVE_LOW));

	gpio_init_callback(&button_cb, button_pressed,
			   BIT(SW0_GPIO_PIN) | BIT(SW1_GPIO_PIN));
	gpio_add_callback(gpio, &button_cb);

	gpio_pin_enable_callback(gpio, SW0_GPIO_PIN);
	gpio_pin_enable_callback(gpio, SW1_GPIO_PIN);
}

void board_init(u16_t *addr, u32_t *seq)
{
	struct mb_display *disp = mb_display_get();

	printk("SEQ_PAGE 0x%08x\n", SEQ_PAGE);

	nvm = device_get_binding(CONFIG_SOC_FLASH_NRF5_DEV_NAME);
	pwm = device_get_binding(CONFIG_PWM_NRF5_SW_0_DEV_NAME);

	*addr = NRF_UICR->CUSTOMER[0];
	if (!*addr || *addr == 0xffff) {
#if defined(NODE_ADDR)
		*addr = NODE_ADDR;
#else
		*addr = 0x0b0c;
#endif
	}

	*seq = get_seq();

	mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED,
			 "0x%04x", *addr);

	configure_button();
}
