
/*
 * leds.c
 *
 *  Created on: 7 Jul 2019
 *      Author: Mike
 */

#include "main.h"
#include "leds.h"

// Target clock rate 800 kHz
#define SPICLOCK 9000000UL
// one clock of SPI is 166nS
#define TSPI (1000000000UL/SPICLOCK)
// reset period is 50000nS
#define TRESET 50000
// total bit period is 1250nS or 1/800kHz
#define TBIT  1250
// to produce '0' value go high for 400nS, low for 850nS
#define T0H    400
#define T0L    850
// to produce '1' value go high for 850nS, low for 400nS
#define T1H    850
#define T1L    400



#define BUFFER_SIZE 1000




uint8_t buffer [BUFFER_SIZE];
// byte pointer
unsigned bufPtr;
// bit index pointer
uint8_t bitPtr;
// bit transmission time offset from start of transmission
unsigned SPItime = 0;

DMX_State_t DMX_State = DMX_IDLE;

unsigned RealTime = 0;

static volatile uint8_t busy = 0;

void initCode(void)
{
	bufPtr = 0;
	bitPtr = 0;
	SPItime  = 0;
	RealTime = 0;
}

// send a '1' or '0' on SPI bus
void codeBit(uint8_t val, unsigned until)
{
	// calculate true limit time
	RealTime += until;
	while(SPItime< RealTime)
	{
	if(val)
	  buffer[bufPtr] |= (1<<bitPtr);
	else
      buffer[bufPtr] &= ~(1<<bitPtr);
	bitPtr++;
	if(bitPtr == 8)
	{
		bitPtr = 0;
		bufPtr ++;
	}
	// accumulate transmission time on SPI bus
	SPItime += TSPI;

	if(bufPtr >= BUFFER_SIZE)
		bufPtr = BUFFER_SIZE-1; // limit
	}
}


void codeReset (void)
{
		codeBit(0,TRESET);
}

// send a single Run Length code bit
void codeRL(uint8_t bit)
{
	unsigned lim = bit ? T1H : T0H;
    	codeBit(1,lim);
    	codeBit(0,TBIT-lim);
}

// code a byte using the RL code
void codeRLByte(uint8_t val)
{
	uint8_t i;
		for (i=0; i<8; i++)
		{
			codeRL(val & 0x80);
			val<<=1;
		}

}

void codeFRGB(frgb_t led )
{

		codeRLByte(((uint16_t)(led.green) * led.fader)/256);
		codeRLByte(((uint16_t)(led.red) * led.fader)/256);
		codeRLByte(((uint16_t)(led.blue) * led.fader)/256);
}



frgb_t led0 = { 128, 0, 0, 0 };
frgb_t ledZ = { 0,0,0,0 };

void sendLeds()
{

	initCode();
	codeReset();

    led0.green++;
	led0.fader++;
    if(led0.green %4 == 0)
		led0.red --;
	if(led0.green %55 == 0)
		led0.blue +=123;
	codeFRGB(led0);
	// send terminal
	codeFRGB(ledZ);
     busy= 1;
	HAL_SPI_Transmit_DMA(&hspi1,buffer,bufPtr+1);
  //
	while(busy) {};
}


void HAL_SPI_TxCpltCallback( SPI_HandleTypeDef * hspi)
{
	(void ) hspi;
	busy = 0;
}



