/**********************************************************************
 *****  COMMON FILE FOR EVERY GILD-SYSTEM PROJECTS                *****
 *****  (WARNING: do not change main routines except user areas)  *****
 *****                                                            *****
 *****  Name: _core_bus.c                                         *****
 *****  Desc: bus control routines 							      *****

 *****  Ver.: 1.0                                                 *****
 *****  Date: 01/2011		                                      *****
 *****  Auth: Martin Mechacek		                              *****
 *****  Comp: ESTELAR s.r.o.									  *****
 *****                                                            *****
 *****  Copyright ESTELAR s.r.o. (c) 2010, all rights reserved    *****
 **********************************************************************/ 



/**********************************************************************
 *****  USER AREA - define dependeces here						  *****
 **********************************************************************/ 



/*

#define PX6 	0x40

#define PBDDR (*(volatile unsigned char *) 0xFEE00A) // Port B data direction register

#define PBDR (*(volatile unsigned char *) 0xFFFFDA) // Port B data register

#define sysLED1(data) 	PBDDR|= 0x01; if(data) PBDR |= 0x01; else PBDR &= ~0x01

#define PADDR (*(volatile unsigned char *) 0xFEE009) // Port A data direction register

#define PADR (*(volatile unsigned char *) 0xFFFFD9) // Port A data register

*/



/////// end of USER AREA //////////////////////////////////////////////





/**********************************************************************
 *****  MAIN AREA - do not change !	   						      *****
 **********************************************************************/ 

#include "_core_def.h" 

#include "_core_bus.h" 





//========================================================================

//>> Global variables


// R8C nema rad promene typu volatile
#if defined CORE_EDK || defined CORE_POW || defined CORE_LOG
  unsigned char gRx[RX_BUFF_SIZE+1];	
  unsigned int  gRxOfs;
  unsigned int  gRxPos;
#else
  volatile unsigned char	gRx[RX_BUFF_SIZE+1];	
  volatile unsigned int		gRxOfs=0, gRxPos=0;
#endif



_bsc  BusControl;


//<< end of Global variables





//+-------------------------------------------------------------------+

//| BusInit()

//| initialise core_bus hardware, and enable sci interrupt

//+-------------------------------------------------------------------+

void BusInit(void)

{


	SET_VTXD(0);

    RS485_DRIVER_TX_LO;

    RX_InterruptEnable;					

	
return;
}  // end of BusInitVar





//+-------------------------------------------------------------------+

//| BusInitVar()

//| initialise core_bus variables

//+-------------------------------------------------------------------+

void BusInitVar(void)

{



  BusControl.Timer_counter=0;

  BusControl.BusState = 0; 			 



  gRxOfs = 0;

  gRxPos = 0;



return;

}  // end of BusInitVar



//+-------------------------------------------------------------------+

//| BusClearBuf()

//| clear the receive buffer

//+-------------------------------------------------------------------+

void BusClearBuf(void)

{

  gRxPos = 0;

  gRxOfs = 0;

  

return;

}  // end of BusClearBuf



//+-------------------------------------------------------------------+

//| BusRecvByte (unsigned char recv)

//| process each received byte from RS485 bus

//+-------------------------------------------------------------------+

unsigned char BusRecvByte (unsigned char recv)

{



// 	BusControl.BusState &= ~BUS_FREE; 		// maze se priznak volne sbernice

//	BusControl.Timer_counter = 0;			// a nuluje se timeout pro znovu nastaveni flagu

	VRXD_DETECTED;



	if( gRxPos <= RX_BUFF_SIZE )			// pokud se preleze velikost paketu data se ztrati !! neni misto 

     {

  		gRx[(gRxOfs+gRxPos)&RX_BUFF_SIZE] = recv;		// read in received data - RDRF-flag is cleared automatically

		gRxPos++;

	 }

	else 

     {

	   return(1);		 

	 }



return(0);

}  // end of BusRecvByte


//sbit LED  = 0x91;


//+-------------------------------------------------------------------+

//| BusPutChar(unsigned int Data)

//| function to send one byte over RS485 bus

//| return 0 when done

//| return > 0 when data collision on bus ocurred

//+-------------------------------------------------------------------+

unsigned int BusPutChar(unsigned int Data)

{		

unsigned char	loop, cnt;





   // Disable all interrupts for accurate timing in BusPutChar

   ALL_InterruptDisable;

   cnt = 1;					



// skutecne vyslana hodnota je negovana, protoze vysilaci pin budice je trvale v nule RS485_DRIVER_TX_LO

// a aktivaci pinu VTXD do jednicky se na sbernici objevi hodnota 0



#ifdef CORE_GR_U01

#if defined HW_VERSION && HW_VERSION < 3



   // pockat dobu jednoho bytu jestli se na lince neco neobjevi

   // protoze o tom, ze vysila nekdo jiny se dozvime az na konci prijeti prvniho celeho bytu

   // pouziva se pouze kdyz neni pin VRXD na vstupu interrupt

   if( (BusControl.BusState & BUS_FIRST) )

    {

	   BusControl.BusState &= ~BUS_FIRST;

	   loop = BITPERIOD1*10;			// 8 bitu + START + STOP

	   while( loop ) 			

	    {

#ifndef __CORE_CPU_ATMEL
	     asm ("nop");		// doplneni na spravne casovani pri rychlosti 19200
#endif
	 	 loop--;

		 if(!VRXD)

		  {

	         // Enable interrupts 

  	         ALL_InterruptEnable;

			 return(3);

		  } 	

		}		

		

	}

#endif

#endif

///////////////////




  /* START BIT */

   if (!VRXD || !(BusControl.BusState&BUS_FREE)) 

    { 

	  ALL_InterruptEnable; 

	  return(1); 

	}

//>>> zacatek mereni konstanty BITPERIOD

   SET_VTXD(1);					// generuj start bit = 0 na linku

   loop = BITPERIOD;

   while( loop ) loop--;		

//<<< konec mereni konstanty BITPERIOD



    /* data bits */

svsenddata:

   if( (unsigned char)Data & cnt ) 		

    {

		SET_VTXD(0);				// log 1 na linku


//>>> zacatek mereni konstanty BITPERIOD1
//>>> zacatek mereni konstanty PERIOD10us

	    loop = PERIOD10us;		// pockat asi 10us nez se aktivuje RS485 driver 

	    while( loop ) 			

	    {

#ifndef __CORE_CPU_ATMEL
	     asm ("nop");		// doplneni na spravne casovani pri rychlosti 19200
#endif

	 	 loop--;

		}	 

//<<< konec mereni konstanty PERIOD10us



	// kontroluje se jestli nasi hodnotu neprebije jine zarizeni ktere vysila log 0

	   loop = BITPERIOD1-PERIOD10us;

	   while( loop ) 			

	    {

#ifndef __CORE_CPU_ATMEL
	     asm ("nop");		// doplneni na spravne casovani pri rychlosti 19200
#endif

	 	 loop--;

		 if(!VRXD)

		  {

	        // Enable interrupts 

    	    ALL_InterruptEnable;

			return(1);

		  } 	

		}		

//<<< konec mereni konstanty BITPERIOD1

	}

   else 						// log 0 na linku

    {

		SET_VTXD(1);

		loop = BITPERIOD;

     	while( loop ) loop--;

	}

  

   cnt <<= 1;

   if( cnt ) goto svsenddata;





    /* stop bit */

   SET_VTXD(0);

   loop = PERIOD10us;

   while( loop ) 			

    {

#ifndef __CORE_CPU_ATMEL
	     asm ("nop");		// doplneni na spravne casovani pri rychlosti 19200
#endif

 	 loop--;

	}	 

		

   // kontroluje se jestli nasi hodnotu neprebije jine zarizeni ktere vysila log 0

   loop = BITPERIOD1-PERIOD10us;

   while( loop ) 			

    {

#ifndef __CORE_CPU_ATMEL
	     asm ("nop");		// doplneni na spravne casovani pri rychlosti 19200
#endif

 	 loop--;

     if(!VRXD)

	  {

	    // Enable interrupts 

  	    ALL_InterruptEnable;

		return(2);

	  } 	

 	}



  // pokud se byte odeslal cely bez preruseni je treba vymazat flagy aby se nezpracoval v ISR

  // kdyz ale dojde k preruseni vysilani tak se prijta data zpracuji - viz predchozi podminka

  RX_ClearFlags;

  

  // take se musi smazat flag preruseni od VRXD

  VRX_ClearFlags;



  // doplneni prodlevy pokud je procesor prilis rychly

  loop = BYTEMARKER;

  while(loop--);



  // Enable interrupts 

  ALL_InterruptEnable;



return(0);

}  // end of BusPutChar





//+-------------------------------------------------------------------+

//| BusTimer (void)

//| Timer routine for bus accurate timing

//| must be called periodically every 1,64ms

//+-------------------------------------------------------------------+

void BusTimer (void)

{

   

	// pokud nebyl prijat zadny znak po stanovenou dobu nastavi se priznak volne sbernice

	if(BusControl.Timer_counter == BUS_FREE_TIMEOUT)

	 {

	  BusControl.Timer_counter++;

	  BusControl.BusState |= BUS_FREE; 

	  BusControl.BusState |= BUS_FIRST;



	  // re-init zpracovani paketu - pripadna spatna data se timto resetuji a muze se zpracovavat znovu spravne

	  // provede se pozdeji pomoci DataInitPacket(), protoze pokud jsou v prijimacim buferu nejaka data musi se nejdrive zpracovat aby sme o ne neprisli

	 }

	 

	// TOTO JE NUTNE, jinak dochazi ke ztrate celeho paketu kdy se zdrzi beh programu a uplyne BUS_FREE_TIMEOUT

	// pokud byl nastaven BUS_FREE, chodi se tudy po vyprazdneni prijimaciho buferu se provede init

	if( BusControl.Timer_counter == (BUS_FREE_TIMEOUT+1) ) 

	 { 	

		 

	    // DataInitPacket probehne az budou zpracovana vsechna data v prijimacim buferu

		if( DataInitPacket() ) BusControl.Timer_counter++; 

	 }



	if( !(BusControl.BusState&BUS_FREE) ) BusControl.Timer_counter++;

	

	if((BusControl.BusState&BUS_TIMEOUT)) BusControl.Timer_counter1++;

	if(BusControl.Timer_counter1 == BUS_WAIT_TIMEOUT)

	 {

	  BusControl.Timer_counter1=0;

	  BusControl.BusState &= ~BUS_TIMEOUT; 			 

	 }



return;

}  // end of BusTimer 







/////// end of MAIN AREA //////////////////////////////////////////////

