/*
 * A library for avr microcontrollers to control WS2812 leds
 *
 * Copyright (C) 2016 Markus Schmidl
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <math.h>

#include "color.h"
#include "ws2812_avr_macros.h"

/* derived from http://fourier.eng.hmc.edu/e161/lectures/ColorProcessing/node3.html */
void Color::hsi2rgb(float h_, float s_, float i_)
{
	h = h_;
	s = s_;
	i = i_;

	h_ = fmod(h_, 360);
	/* convert h to radiants */
	h_ = M_PI * h_ / 180.0;
	/* clamp s and i to interval [0:1] */
	s_ = clamp_to_0_1(s_);
	i_ = clamp_to_0_1(i_);

	if (s_ == 0.0) {
		r = g = b = i_ * 255;
	} else {
		float r_, g_, b_;
#define hsi2rgb_color1 ((1 - s_) / 3)
#define hsi2rgb_color2 ((1 + s_ * cos(h_) / cos((M_PI / 3.0) - h_)) / 3)
		if ((h_ >= 0.0) && (h_ < 2.0 * M_PI / 3.0)) {
			b_ = hsi2rgb_color1;
			r_ = hsi2rgb_color2;
			g_ = 1 - b_ - r_;
		} else if ((h_ >= 2.0 * M_PI / 3.0) && (h_ < 4.0 * M_PI / 3.0)) {
			h_ -= 2.0 * M_PI / 3.0;
			r_ = hsi2rgb_color1;
			g_ = hsi2rgb_color2;
			b_ = 1 - r_ - g_;
		} else {
			h_ -= 4.0 * M_PI / 3.0;
			g_ = hsi2rgb_color1;
			b_ = hsi2rgb_color2;
			r_ = 1 - g_ - b_;
		}

		r_ =  i_ * r_ * 255;
		g_ =  i_ * g_ * 255;
		b_ =  i_ * b_ * 255;

		/* clamp r, g and b to interval [0:255] */
		r = clamp_to_0_255(r_);
		g = clamp_to_0_255(g_);
		b = clamp_to_0_255(b_);
	}
	
}
