/*

	Led Ring Driver
	---------------
	
	This code is designed to drive the Memecode LED ring v1.
	The MLR1 has 16 RGB LEDs arranging in a circle with one
	in the 6 oclock position and 15 in an arc running from
	7:30 through to 4:30.
	
	The LED's are driven via three TLC5925 chips (16 lights
	each). 48 bits of RGB data is written to the SPI port
	each time an update is required. Multiple LED rings can
	be chained together by hooking the output pin of one
	to the input pin of another.
	
	The first parameter to each function is an array of 3
	16-bit integers that contain the state of each LED.

*/
#include <io.h>

#include "led-ring.h"
#include "spi.h"

void LedRing_SetColour(uint16 *Ring, int Led, int Colour)
{
	#define SET_RGB_BIT(bit) \
		Ring[bit >> 4] |= 1 << (bit & 0xf);
	
	#define CLR_RGB_BIT(bit) \
		Ring[bit >> 4] &= ~(1 << (bit & 0xf));
		
	#define SET_RGB(rbit, gbit, bbit) \
			if (Colour & LedRed)   SET_RGB_BIT(rbit) else CLR_RGB_BIT(rbit); \
			if (Colour & LedGreen) SET_RGB_BIT(gbit) else CLR_RGB_BIT(gbit); \
			if (Colour & LedBlue)  SET_RGB_BIT(bbit) else CLR_RGB_BIT(bbit);
	
	switch (Led)
	{
		case 0:
			SET_RGB(29, 27, 25);
			break;
		case 1:
			SET_RGB(26, 24, 7);
			break;
		case 2:
			SET_RGB(1, 3, 5);
			break;
		case 3:
			SET_RGB(2, 4, 6);
			break;
		case 4:
			SET_RGB(15, 0, 13);
			break;
		case 5:
			SET_RGB(12, 11, 9);
			break;
		case 6:
			SET_RGB(14, 10, 8);
			break;
		case 7:
			SET_RGB(46, 34, 32);
			break;
		case 8:
			SET_RGB(40, 42, 44);
			break;
		case 9:
			SET_RGB(43, 45, 47);
			break;
		case 10:
			SET_RGB(38, 36, 41);
			break;
		case 11:
			SET_RGB(33, 37, 35);
			break;
		case 12:
			SET_RGB(17 /* ???? */, 19, 39);
			break;
		case 13:
			SET_RGB(18, 23, 21);
			break;
		case 14:
			SET_RGB(22, 20, 16);
			break;
		case 15:
			SET_RGB(31, 28, 30);
			break;
	}
}

void LedRing_Update(uint16 *Ring)
{
	SET_PIN(F, SO_OUTPUT_ENABLE);

	spiWrite16(Ring[2]);
	spiWrite16(Ring[1]);
	spiWrite16(Ring[0]);

	CLR_PIN(F, SO_OUTPUT_ENABLE);
}