/* dmx_in Library (DMX reception lib, C version)
 ****************************************************************************
 * Author:      Hendrik Hlscher                         					*
 * modified by:    															*
 * Revision:    1.1                              							*
 * Date:        19.06.06                  									*
 * Target:      Transceiver Rev.3.01 (www.hoelscher-hi.de)        			*
 * Compiled using AVRStudio4                 								*
 ****************************************************************************
 * Fuses:    OSC:  8.0 Mhz xtal	          									*
 *           WDT:  OFF                       								*
 ****************************************************************************
 *                   Software License Agreement                       		*
 *                                                                    		*
 * The software supplied herewith by Henne's Sites is intended and          *
 * supplied to you for use in  Applications based on it's DMX-Transceiver.	*
 * This header must be part of any version of this software.				*
 * Any version of this software must be compatible with the Transceiver.	*
 * (This can be achieved using compiler flags.) The software is owned by 	*
 * Henne's Sites, and is protected under applicable copyright laws.			*
 * All rights are reserved. 												*
 * 					                              							*
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,   		*
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED   		*
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 	      		*
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. HENNE'S SITES SHALL NOT,   	*
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 	      		*
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.	              		*
 ****************************************************************************
 */

#include "lib_dmx_in.h"
#include "lib_indicator.h"

// ********************* local definitions *********************

enum {IDLE, BREAK, STARTB, STARTADR};			//DMX states

		 uint8_t 	 gDmxState;
		 uint8_t 	*gDmxPnt;
		 uint16_t	 DmxCount;


// *************** DMX Reception Initialisation ****************
void init_DMX(void)
{
#ifdef DIPSWITCH
DDRC= 0;							//set up DIPs
PORTC= 0xFF;
DDRE &= ~(1<<2);
PORTE |= (1<<2);
#endif

UBRRH  = 0;
UBRRL  = ((F_OSC/4000)-1);			//250kbaud, 8N2
UCSRC |= (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB |= (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;

uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
	{
	DmxField[i]= 0;
	}

}


// ************* get DMX start address **************
void get_dips(void)
{
#ifdef DIPSWITCH
uint16_t Temp= (255-PINC);			//invert DIP state
if (!(PINE &(1<<2)))
	{
	Temp= Temp +256;				//9th bit
	}

if (Temp != 0)
	if (!(PINB &(1<<4)))
	{
	Temp= Temp +4;					//add 4 to DMX address to use as slave
	}
	DmxAddress= Temp;
	if (!(UCSRB &(1<<RXCIE)))		//if receiver was disabled -> enable and wait for break
		{
		gDmxState= IDLE;
		UCSRB |= (1<<RXCIE);
		}
	
else
	{
	UCSRB &= ~(1<<RXCIE);			//disable Receiver if start address = 0
	for (Temp=0; Temp<DMX_CHANNELS; Temp++)
		{
		DmxField[Temp]= 0;
		}
	Flags |= (1<<EVAL_DMX);		//data set ready -> eval in main
	}
#endif 
}


// *************** DMX Reception ISR ****************
ISR (UART_RX_vect)
{
uint8_t USARTstate= UCSRA;			//get state
uint8_t DmxByte= UDR;				//get data
uint8_t DmxState= gDmxState;		//just get once from SRAM!!!

IndFlags |= (1<<SIGNAL_COMING);		//receiving some data
 
if (DmxState == BREAK)
	{
	UCSRA &= ~(1<<FE);				//reset possible FE because of MAB	
	if (DmxByte == 0) 
		{
		gDmxState= STARTB;			//normal start code detected
		gDmxPnt= ((uint8_t*)DmxField +1);
		}
	else
		{
		gDmxState= IDLE;
		}
	}

else if (USARTstate &(1<<FE))		//check for break
	{
	UCSRA &= ~(1<<FE);				//reset flag
	if (DmxByte == 0)				//data in break must be 0
		{
		gDmxState= BREAK;
		DmxCount= DmxAddress;		//reset frame counter
		}
	else
		{
		gDmxState= IDLE;			//real FE -> wait for break
		}
	}
	
else if (DmxState == STARTB)
	{
	if (--DmxCount == 0)			//start address reached?
		{
		gDmxState= STARTADR;
		DmxField[0]= DmxByte;
		}
	}

else if (DmxState == STARTADR)
	{
	uint8_t *DmxPnt;
	DmxPnt= gDmxPnt;
	*DmxPnt= DmxByte;
	if (++DmxPnt >= (DmxField +DMX_CHANNELS)) //all ch received?
		{
		Flags |= (1<<EVAL_DMX);		//data set ready -> eval in main
		gDmxState= IDLE;
		}
	else
		{
		gDmxPnt= DmxPnt;
		}
	}							
}


