/****************************************************************************/
/*
 * MODULE              JN-AN-1162 JenNet-IP Smart Home
 *
 * DESCRIPTION         Colour Transition Implementation
 */
/****************************************************************************/
/*
 * This software is owned by NXP B.V. and/or its supplier and is protected
 * under applicable copyright laws. All rights are reserved. We grant You,
 * and any third parties, a license to use this software solely and
 * exclusively on NXP products [NXP Microcontrollers such as JN5168, JN5164].
 * You, and any third parties must reproduce the copyright and warranty notice
 * and any other legend of ownership on each copy or partial copy of the
 * software.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright NXP B.V. 2014. All rights reserved
 */
/****************************************************************************/

/****************************************************************************/
/***        Include files                                                 ***/
/****************************************************************************/
/* Standard includes */
#include <string.h>
#include <stdlib.h>
#include <math.h>
/* SDK includes */
#include <jendefs.h>
/* JenOS includes */
#include <dbg.h>
#include <dbg_uart.h>
/* Application common includes */
/* Application includes */
#include "DeviceDefs.h"
#include "ColourConversion.h"
#include "ColourTransition.h"
#include "Interpolation.h"

/****************************************************************************/
/***        Macro Definitions                                             ***/
/****************************************************************************/

/****************************************************************************/
/***        Type Definitions                                              ***/
/****************************************************************************/

/****************************************************************************/
/***        Local Function Prototypes                                     ***/
/****************************************************************************/
PRIVATE bool_t ColourTransition_bRGBInit(tsColourTransition *psColourTransition);
PRIVATE bool_t ColourTransition_bRGBJump(tsColourTransition *psColourTransition);

/****************************************************************************/
/***        Exported Variables                                            ***/
/****************************************************************************/

/****************************************************************************/
/***        Local Variables                                               ***/
/****************************************************************************/

/****************************************************************************/
/***        Exported Functions                                            ***/
/****************************************************************************/

/****************************************************************************
 *
 * NAME: ColourTransition_vXYStart
 *
 * DESCRIPTION:
 * Starts transition across XY space
 *
 * The XY interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		au32Source;
 * 		au32Target;
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 * The HS interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The CCT interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The RGB interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bXYStart(tsColourTransition *psColourTransition)
{
	bool_t bReturn;

	/* Start the XY interpolation */
	bReturn = Interpolation_bStart(&psColourTransition->sXYInterpolation);
	/* Success ? */
	if (bReturn)
	{
		/* Transfer HS source to HS source step and HS target step values (Interpolation_bStart() does this for XY) */
		psColourTransition->sHSInterpolation.au32SourceStep[H_DIM]    = psColourTransition->sHSInterpolation.au32Source[H_DIM];
		psColourTransition->sHSInterpolation.au32SourceStep[S_DIM]    = psColourTransition->sHSInterpolation.au32Source[S_DIM];
		psColourTransition->sHSInterpolation.au32TargetStep[H_DIM]    = psColourTransition->sHSInterpolation.au32Source[H_DIM];
		psColourTransition->sHSInterpolation.au32TargetStep[S_DIM]    = psColourTransition->sHSInterpolation.au32Source[S_DIM];
		/* Transfer CCT source to CCT source step and CCT target step values (Interpolation_bStart() does this for XY) */
		psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32Source[CCT_DIM];
		psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32Source[CCT_DIM];

		/* Calculate first XY interpolation step */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sXYInterpolation);
		/* Success ? */
		if (bReturn)
		{
			uint16 u16H;
			uint8   u8S;
			uint8   u8V;
			uint16 u16Cct;

			/* Convert step target XY to HS */
			eCLD_ColourControl_xyY2HSV(
				psColourTransition->psColourData,
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
				(uint8) 255,
				&u16H,
				&u8S,
				&u8V);
			/* Transfer old HS target step to new HS source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
			psColourTransition->sHSInterpolation.au32SourceStep[H_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[H_DIM];
			psColourTransition->sHSInterpolation.au32SourceStep[S_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[S_DIM];
			/* Transfer new converted HS target step */
			psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = (uint32) u16H;
			psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = (uint32) u8S;

			/* Convert step target XY to CCT */
			vCLD_ColourControl_xyY2CCT(
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
				(uint8) 255,
				&u16Cct);
			/* Transfer old CCT target step to new CCT source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
			psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM];
			/* Transfer new converted CCT target step */
			psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = (uint32) u16Cct;

			/* Setup initial RGB transition */
			bReturn = ColourTransition_bRGBInit(psColourTransition);
		}
	}

	/* Success ? */
	if (bReturn)
	{
		/* Set the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_XY;
	}
	else
	{
		/* Clear the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
	}

	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bXYStart((0x%x, 0x%x) > (0x%x, 0x%x) in %d steps) = %d",
		psColourTransition->sXYInterpolation.au32Source[X_DIM],
		psColourTransition->sXYInterpolation.au32Source[Y_DIM],
		psColourTransition->sXYInterpolation.au32Target[X_DIM],
		psColourTransition->sXYInterpolation.au32Target[Y_DIM],
		psColourTransition->sXYInterpolation.u32Steps,
		bReturn);

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_bXYNext
 *
 * DESCRIPTION:
 * Next step in transition across XY space
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bXYNext(tsColourTransition *psColourTransition)
{
	bool_t bReturn = FALSE;

	/* Got some steps left to do ? */
	if (psColourTransition->sRGBInterpolation.u32RemainingSteps > 0)
	{
		/* Calculate next step of RGB interpolation */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sRGBInterpolation);
		/* Was that the last RGB interpolation in within this XY interpolation ? */
		if (psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* Are there some steps left in the XY interpolation ? */
			if (psColourTransition->sXYInterpolation.u32RemainingSteps > 0)
			{
				uint16 u16H;
				uint8   u8S;
				uint8   u8V;
				uint16 u16Cct;

				/* Calculate next step in XY interpolation */
				bReturn = Interpolation_bInterpolate(&psColourTransition->sXYInterpolation);

				/* Convert step target XY to HS */
				eCLD_ColourControl_xyY2HSV(
					psColourTransition->psColourData,
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
					(uint8) 255,
					&u16H,
					&u8S,
					&u8V);
				/* Transfer old HS target step to new HS source step (before we change it) */
				psColourTransition->sHSInterpolation.au32SourceStep[H_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[H_DIM];
				psColourTransition->sHSInterpolation.au32SourceStep[S_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[S_DIM];
				/* Transfer new converted HS target step */
				psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = (uint32) u16H;
				psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = (uint32) u8S;

				/* Convert step target XY to CCT */
				vCLD_ColourControl_xyY2CCT(
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
					(uint8) 255,
					&u16Cct);
				/* Transfer old CCT target step to new CCT source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
				psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM];
				/* Transfer new converted CCT target step */
				psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = (uint32) u16Cct;

				/* Set up next RGB inner interpolation */
				bReturn = ColourTransition_bRGBJump(psColourTransition);
			}
		}
		/* Finished XY transition ? */
		if (psColourTransition->sXYInterpolation.u32RemainingSteps  == 0 &&
		    psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* No longer transitioning */
			psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
		}
	}

#if 0
	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bXYNext(XY %d = (0x%x, 0x%x), RGB %d = (0x%x, 0x%x, 0x%x)) = %d",
		psColourTransition->sXYInterpolation.u32RemainingSteps,
		psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
		psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
		psColourTransition->sRGBInterpolation.u32RemainingSteps,
		psColourTransition->sRGBInterpolation.au32TargetStep[R_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[G_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[B_DIM],
		bReturn);
#endif

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_vHSStart
 *
 * DESCRIPTION:
 * Starts transition across HS space
 *
 * The HS interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		au32Source;
 * 		au32Target;
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 * The XY interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The CCT interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The RGB interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bHSStart(tsColourTransition *psColourTransition, bool_t bOptimise)
{
	bool_t bReturn;

	/* Want to optimise transition (take the shortest route) ? */
	if (bOptimise)
	{
		/* Is target hue larger than source hue ? */
		if (psColourTransition->sHSInterpolation.au32Target[H_DIM] > psColourTransition->sHSInterpolation.au32Source[H_DIM])
		{
			/* Is the difference more than 180 degrees ? */
			if (psColourTransition->sHSInterpolation.au32Target[H_DIM] - psColourTransition->sHSInterpolation.au32Source[H_DIM] > 1800)
			{
				/* Add 360 degrees to source to transition across red more efficiently */
				psColourTransition->sHSInterpolation.au32Source[H_DIM] += 3600;
			}
		}
		/* Source hue is larger than target hue ? */
		else
		{
			/* Is the difference more than 180 degrees ? */
			if (psColourTransition->sHSInterpolation.au32Source[H_DIM] - psColourTransition->sHSInterpolation.au32Target[H_DIM] > 1800)
			{
				/* Add 360 degrees to target to transition across red more efficiently */
				psColourTransition->sHSInterpolation.au32Target[H_DIM] += 3600;
			}
		}
	}

	/* Start the HS interpolation */
	bReturn = Interpolation_bStart(&psColourTransition->sHSInterpolation);
	/* Success ? */
	if (bReturn)
	{
		/* Transfer XY source to XY source step and XY target step values (Interpolation_bStart() does this for HS) */
		psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32Source[X_DIM];
		psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32Source[Y_DIM];
		psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = psColourTransition->sXYInterpolation.au32Source[X_DIM];
		psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = psColourTransition->sXYInterpolation.au32Source[Y_DIM];
		/* Transfer CCT source to CCT source step and CCT target step values (Interpolation_bStart() does this for XY) */
		psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32Source[CCT_DIM];
		psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32Source[CCT_DIM];

		/* Calculate first HS interpolation step */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sHSInterpolation);
		/* Success ? */
		if (bReturn)
		{
			uint16 u16X;
			uint16 u16Y;
			uint8   u8BigY;
			uint16 u16Cct;

			/* Convert step target HS to XY */
			eCLD_ColourControl_HSV2xyY(
				psColourTransition->psColourData,
				(uint16) (psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] % 3600),
				(uint8)   psColourTransition->sHSInterpolation.au32TargetStep[S_DIM],
				(uint8) 255,
        		&u16X,
        		&u16Y,
        		&u8BigY);
			/* Transfer old XY target step to new XY source step (before we change it) (Interpolation_bInterpolate() does this for HS) */
			psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[X_DIM];
			psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM];
			/* Transfer new converted XY target step */
			psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = (uint32) u16X;
			psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = (uint32) u16Y;

			/* Convert step target XY to CCT */
			vCLD_ColourControl_xyY2CCT(
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
				(uint8) 255,
				&u16Cct);
			/* Transfer old CCT target step to new CCT source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
			psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM];
			/* Transfer new converted CCT target step */
			psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = (uint32) u16Cct;

			/* Set up initial RGB transition */
			bReturn = ColourTransition_bRGBInit(psColourTransition);
		}
	}

	/* Success ? */
	if (bReturn)
	{
		/* Set the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_HS;
	}
	else
	{
		/* Clear the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
	}

	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bHSStart((%d, %d) > (%d, %d) in %d steps) = %d",
		psColourTransition->sHSInterpolation.au32Source[H_DIM],
		psColourTransition->sHSInterpolation.au32Source[S_DIM],
		psColourTransition->sHSInterpolation.au32Target[H_DIM],
		psColourTransition->sHSInterpolation.au32Target[S_DIM],
		psColourTransition->sHSInterpolation.u32Steps,
		bReturn);

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_bHSNext
 *
 * DESCRIPTION:
 * Next step in transition across XY space
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bHSNext(tsColourTransition *psColourTransition)
{
	bool_t bReturn = FALSE;

	/* Got some steps left to do ? */
	if (psColourTransition->sRGBInterpolation.u32RemainingSteps > 0)
	{
		/* Calculate next step of RGB interpolation */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sRGBInterpolation);
		/* Was that the last RGB interpolation in within this HS interpolation ? */
		if (psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* Are there some steps left in the HS interpolation ? */
			if (psColourTransition->sHSInterpolation.u32RemainingSteps > 0)
			{
				uint16 u16X;
				uint16 u16Y;
				uint8   u8BigY;
				uint16 u16Cct;

				/* Calculate next step in HS interpolation */
				bReturn = Interpolation_bInterpolate(&psColourTransition->sHSInterpolation);

				/* Convert step target HS to XY */
				eCLD_ColourControl_HSV2xyY(
					psColourTransition->psColourData,
					(uint16) (psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] % 3600),
					(uint8)   psColourTransition->sHSInterpolation.au32TargetStep[S_DIM],
					(uint8) 255,
					&u16X,
					&u16Y,
					&u8BigY);
				/* Transfer old XY target step to new XY source step (before we change it) (Interpolation_bInterpolate() does this for HS) */
				psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[X_DIM];
				psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM];
				/* Transfer new converted XY target step */
				psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = (uint32) u16X;
				psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = (uint32) u16Y;

				/* Convert step target XY to CCT */
				vCLD_ColourControl_xyY2CCT(
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
					(uint8) 255,
					&u16Cct);
				/* Transfer old CCT target step to new CCT source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
				psColourTransition->sCctInterpolation.au32SourceStep[CCT_DIM] = psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM];
				/* Transfer new converted CCT target step */
				psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = (uint32) u16Cct;

				/* Set up next RGB inner interpolation */
				bReturn = ColourTransition_bRGBJump(psColourTransition);
			}
		}
		/* Finished HS transition ? */
		if (psColourTransition->sHSInterpolation.u32RemainingSteps  == 0 &&
		    psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* No longer transitioning */
			psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
		}
	}

#if 0
	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bHSNext(HS %d = (%d, %d), RGB %d = (0x%x, 0x%x, 0x%x)) = %d",
		psColourTransition->sHSInterpolation.u32RemainingSteps,
		psColourTransition->sHSInterpolation.au32TargetStep[H_DIM],
		psColourTransition->sHSInterpolation.au32TargetStep[S_DIM],
		psColourTransition->sRGBInterpolation.u32RemainingSteps,
		psColourTransition->sRGBInterpolation.au32TargetStep[R_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[G_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[B_DIM],
		bReturn);
#endif

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_vCctStart
 *
 * DESCRIPTION:
 * Starts transition across CCT space
 *
 * The CCT interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		au32Source;
 * 		au32Target;
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 * The XY interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The HS interpolation struture should have these members filled in by the
 * calling function (this is kept in sync with the XY transition):
 *
 * 		au32Source;
 * 		au32Target;
 *        u8Dimensions;
 *
 * The RGB interpolation struture should have these members filled in by the
 * calling function:
 *
 * 		 u8StepsPowerOfTwo;
 * 		u32Steps;
 * 		 u8Dimensions;
 * 		 u8Bits;
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bCctStart(tsColourTransition *psColourTransition)
{
	bool_t bReturn;

	/* Start the CCT interpolation */
	bReturn = Interpolation_bStart(&psColourTransition->sCctInterpolation);
	/* Success ? */
	if (bReturn)
	{
		/* Transfer XY source to XY source step and XY target step values (Interpolation_bStart() does this for HS) */
		psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32Source[X_DIM];
		psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32Source[Y_DIM];
		psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = psColourTransition->sXYInterpolation.au32Source[X_DIM];
		psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = psColourTransition->sXYInterpolation.au32Source[Y_DIM];
		/* Transfer HS source to HS source step and HS target step values (Interpolation_bStart() does this for XY) */
		psColourTransition->sHSInterpolation.au32SourceStep[H_DIM] = psColourTransition->sHSInterpolation.au32Source[H_DIM];
		psColourTransition->sHSInterpolation.au32SourceStep[S_DIM] = psColourTransition->sHSInterpolation.au32Source[S_DIM];
		psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = psColourTransition->sHSInterpolation.au32Source[H_DIM];
		psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = psColourTransition->sHSInterpolation.au32Source[S_DIM];

		/* Calculate first CCT interpolation step */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sCctInterpolation);
		/* Success ? */
		if (bReturn)
		{
			uint16 u16X;
			uint16 u16Y;
			uint8   u8BigY;
			uint16 u16H;
			uint8   u8S;
			uint8   u8V;

			/* Convert step target CCT to XY */
			vCLD_ColourControl_CCT2xyY(
				(uint16) psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM],
        		&u16X,
        		&u16Y,
        		&u8BigY);
			/* Transfer old XY target step to new XY source step (before we change it) (Interpolation_bInterpolate() does this for HS) */
			psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[X_DIM];
			psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM];
			/* Transfer new converted XY target step */
			psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = (uint32) u16X;
			psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = (uint32) u16Y;

			/* Convert step target XY to HS */
			eCLD_ColourControl_xyY2HSV(
				psColourTransition->psColourData,
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
				(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
				(uint8) 255,
				&u16H,
				&u8S,
				&u8V);
			/* Transfer old HS target step to new HS source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
			psColourTransition->sHSInterpolation.au32SourceStep[H_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[H_DIM];
			psColourTransition->sHSInterpolation.au32SourceStep[S_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[S_DIM];
			/* Transfer new converted HS target step */
			psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = (uint32) u16H;
			psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = (uint32) u8S;

			/* Set up initial RGB transition */
			bReturn = ColourTransition_bRGBInit(psColourTransition);
		}
	}

	/* Success ? */
	if (bReturn)
	{
		/* Set the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_CCT;
	}
	else
	{
		/* Clear the mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
	}

	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bCctStart(%d > %d in %d steps) = %d",
		psColourTransition->sCctInterpolation.au32Source[CCT_DIM],
		psColourTransition->sCctInterpolation.au32Target[CCT_DIM],
		psColourTransition->sCctInterpolation.u32Steps,
		bReturn);

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_bCctNext
 *
 * DESCRIPTION:
 * Next step in transition across CCT space
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bCctNext(tsColourTransition *psColourTransition)
{
	bool_t bReturn = FALSE;

	/* Got some steps left to do ? */
	if (psColourTransition->sRGBInterpolation.u32RemainingSteps > 0)
	{
		/* Calculate next step of RGB interpolation */
		bReturn = Interpolation_bInterpolate(&psColourTransition->sRGBInterpolation);
		/* Was that the last RGB interpolation in within this HS interpolation ? */
		if (psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* Are there some steps left in the CCT interpolation ? */
			if (psColourTransition->sCctInterpolation.u32RemainingSteps > 0)
			{
				uint16 u16X;
				uint16 u16Y;
				uint8   u8BigY;
				uint16 u16H;
				uint8   u8S;
				uint8   u8V;

				/* Calculate next step in CCT interpolation */
				bReturn = Interpolation_bInterpolate(&psColourTransition->sCctInterpolation);

				/* Convert step target CCT to XY */
				vCLD_ColourControl_CCT2xyY(
					(uint16) psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM],
					&u16X,
					&u16Y,
					&u8BigY);
				/* Transfer old XY target step to new XY source step (before we change it) (Interpolation_bInterpolate() does this for HS) */
				psColourTransition->sXYInterpolation.au32SourceStep[X_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[X_DIM];
				psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM] = psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM];
				/* Transfer new converted XY target step */
				psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = (uint32) u16X;
				psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = (uint32) u16Y;

				/* Convert step target XY to HS */
				eCLD_ColourControl_xyY2HSV(
					psColourTransition->psColourData,
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
					(uint16) psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
					(uint8) 255,
					&u16H,
					&u8S,
					&u8V);
				/* Transfer old HS target step to new HS source step (before we change it) (Interpolation_bInterpolate() does this for XY) */
				psColourTransition->sHSInterpolation.au32SourceStep[H_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[H_DIM];
				psColourTransition->sHSInterpolation.au32SourceStep[S_DIM] = psColourTransition->sHSInterpolation.au32TargetStep[S_DIM];
				/* Transfer new converted HS target step */
				psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = (uint32) u16H;
				psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = (uint32) u8S;

				/* Set up next RGB inner interpolation */
				bReturn = ColourTransition_bRGBJump(psColourTransition);
			}
		}
		/* Finished CCT transition ? */
		if (psColourTransition->sCctInterpolation.u32RemainingSteps  == 0 &&
		    psColourTransition->sRGBInterpolation.u32RemainingSteps == 0)
		{
			/* No longer transitioning */
			psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
		}
	}

#if 0
	/* Debug */
	DBG_vPrintf(DEBUG_COLOUR_TRANSITION, "\nColourTransition_bCctNext(HS %d = %d, RGB %d = (0x%x, 0x%x, 0x%x)) = %d",
		psColourTransition->sCctInterpolation.u32RemainingSteps,
		psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM],
		psColourTransition->sRGBInterpolation.u32RemainingSteps,
		psColourTransition->sRGBInterpolation.au32TargetStep[R_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[G_DIM],
		psColourTransition->sRGBInterpolation.au32TargetStep[B_DIM],
		bReturn);
#endif

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_bEnd
 *
 * DESCRIPTION:
 * End transition
 *
 ****************************************************************************/
PUBLIC bool_t ColourTransition_bEnd(tsColourTransition *psColourTransition)
{
	bool_t bReturn = FALSE;

	/* Is a transition running ? */
	if (COLOUR_TRANSITION_MODE_NONE != psColourTransition->u8Mode)
	{
		uint16                      u16x;
		uint16                      u16y;
		uint8                        u8Y;
		uint16                      u16H;
		uint8                        u8S;
		uint8                        u8V;
		uint16 						u16Cct;

		/* Clear mode */
		psColourTransition->u8Mode = COLOUR_TRANSITION_MODE_NONE;
		/* End all interpolations */
		Interpolation_bEnd(&psColourTransition->sRGBInterpolation);
		Interpolation_bEnd(&psColourTransition->sXYInterpolation);
		Interpolation_bEnd(&psColourTransition->sHSInterpolation);
		Interpolation_bEnd(&psColourTransition->sCctInterpolation);
		/* Convert target step RGB value back to xyY */
		eCLD_ColourControl_RGB2xyY(
				psColourTransition->psColourData,
				 psColourTransition->sRGBInterpolation.au32TargetStep[R_DIM],
				 psColourTransition->sRGBInterpolation.au32TargetStep[G_DIM],
				 psColourTransition->sRGBInterpolation.au32TargetStep[B_DIM],
				&u16x,
				&u16y,
				&u8Y);
		/* Write converted values into xy target step */
		psColourTransition->sXYInterpolation.au32TargetStep[X_DIM] = u16x;
		psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM] = u16y;
		/* Convert target step xy to HS */
		eCLD_ColourControl_xyY2HSV(
			psColourTransition->psColourData,
        	u16x,
        	u16y,
        	255,
        	&u16H,
        	&u8S,
        	&u8V);
		/* Write converted values into HS target step */
		psColourTransition->sHSInterpolation.au32TargetStep[H_DIM] = u16H;
		psColourTransition->sHSInterpolation.au32TargetStep[S_DIM] = u8S;
		/* Convert target step xy to CCT */
		vCLD_ColourControl_xyY2CCT(
        	u16x,
        	u16y,
        	255,
        	&u16Cct);
		/* Write converted values into HS target step */
		psColourTransition->sCctInterpolation.au32TargetStep[CCT_DIM] = u16Cct;

		/* Stopped a transition */
		bReturn = TRUE;
	}

	return bReturn;
}

/****************************************************************************/
/***        Local Functions                                               ***/
/****************************************************************************/

/****************************************************************************
 *
 * NAME: ColourTransition_bRGBInit
 *
 * DESCRIPTION:
 * Starts transition across RGB space converting from XY
 *
 ****************************************************************************/
PRIVATE bool_t ColourTransition_bRGBInit(tsColourTransition *psColourTransition)
{
	bool_t   bReturn;
	uint8  au8RGB[RGB_DIMS];

	/* Calculate RGB source for first step of the XY interpolation */
	eCLD_ColourControl_GetRGB(psColourTransition->psColourData,
							  psColourTransition->sXYInterpolation.au32SourceStep[X_DIM],
							  psColourTransition->sXYInterpolation.au32SourceStep[Y_DIM],
							  &au8RGB[R_DIM],
							  &au8RGB[G_DIM],
							  &au8RGB[B_DIM]);
	/* Copy RGB source into RGB interpolation structure */
	psColourTransition->sRGBInterpolation.au32Source[R_DIM] = (uint32) au8RGB[R_DIM];
	psColourTransition->sRGBInterpolation.au32Source[G_DIM] = (uint32) au8RGB[G_DIM];
	psColourTransition->sRGBInterpolation.au32Source[B_DIM] = (uint32) au8RGB[B_DIM];

	/* Calculate RGB target for first step of the XY interpolation */
	eCLD_ColourControl_GetRGB(psColourTransition->psColourData,
							  psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
							  psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
							  &au8RGB[R_DIM],
							  &au8RGB[G_DIM],
							  &au8RGB[B_DIM]);
	/* Copy RGB source into RGB interpolation structure */
	psColourTransition->sRGBInterpolation.au32Target[R_DIM] = (uint32) au8RGB[R_DIM];
	psColourTransition->sRGBInterpolation.au32Target[G_DIM] = (uint32) au8RGB[G_DIM];
	psColourTransition->sRGBInterpolation.au32Target[B_DIM] = (uint32) au8RGB[B_DIM];

	/* Start the RGB interpolation */
	bReturn = Interpolation_bStart(&psColourTransition->sRGBInterpolation);

	return bReturn;
}

/****************************************************************************
 *
 * NAME: ColourTransition_bRGBJump
 *
 * DESCRIPTION:
 * Next step in transition across RGB space converting from XY space
 *
 ****************************************************************************/
PRIVATE bool_t ColourTransition_bRGBJump(tsColourTransition *psColourTransition)
{
	bool_t   bReturn = FALSE;
	uint8  au8RGB[RGB_DIMS];

	/* Source for next RGB interpolation is current target */
	psColourTransition->sRGBInterpolation.au32Source[R_DIM] = psColourTransition->sRGBInterpolation.au32Target[R_DIM];
	psColourTransition->sRGBInterpolation.au32Source[G_DIM] = psColourTransition->sRGBInterpolation.au32Target[G_DIM];
	psColourTransition->sRGBInterpolation.au32Source[B_DIM] = psColourTransition->sRGBInterpolation.au32Target[B_DIM];
	/* Convert XY step target to RGB to use a target for next RGB interpolation */
	eCLD_ColourControl_GetRGB(psColourTransition->psColourData,
							  psColourTransition->sXYInterpolation.au32TargetStep[X_DIM],
							  psColourTransition->sXYInterpolation.au32TargetStep[Y_DIM],
							  &au8RGB[R_DIM],
							  &au8RGB[G_DIM],
							  &au8RGB[B_DIM]);
	/* Copy RGB source into RGB interpolation structure */
	psColourTransition->sRGBInterpolation.au32Target[R_DIM] = (uint32) au8RGB[R_DIM];
	psColourTransition->sRGBInterpolation.au32Target[G_DIM] = (uint32) au8RGB[G_DIM];
	psColourTransition->sRGBInterpolation.au32Target[B_DIM] = (uint32) au8RGB[B_DIM];
	/* Start the next RGB interpolation (step target will be set to source so calling functions can use it) */
	bReturn = Interpolation_bStart(&psColourTransition->sRGBInterpolation);

	return bReturn;
}

/****************************************************************************/
/***        END OF FILE                                                   ***/
/****************************************************************************/
