#include "compiler.h"
#include "mb90495.h"
#include "vectors.h"
#include "can.h"
#include "hardware.h"
#include "uart.h"
#include "timer.h"
#include "i2c.h"
#include "eeprom.h"
#include "adi.h"
#include "pwm.h"
#include "mcan.h"
#include "udcount.h"

// Example for an incremental rotation switch.
// Required signal shape:
// Signal A:____----____----__
// Signal B:--____----____----
// It is required that both outputs create a continuous signal.
// Example: Grayhill rotary encoder.

// The following waveshape is not supported:
// Signal A: ____--____--____
// Signal B: ___--____--____-
// Reason: The incremenrtal inputs are not interrupt-driven, the state of
// the inputs are sampled within the timer interrupt. Therefor
// the function "UDC_Server() might miss transmissions and therefor
// count wrong.

// The maximum signal change rate is one transition per Millisecond.
// (one signal change of Signal A or Signal B)

//*************************************************************
static void Eval_CANFrames(void);			//CAN receive function
//***********************************************************************
// CAN-Queues
#define QUEUE_RCV_SIZE	8	// reserve memory for CAN-Queue, count must be 2,4,8,16,...
#define QUEUE_XMT_SIZE	8	// reserve memory for CAN-Queue, count must be 2,4,8,16,...
//**************************************************************
//UART-Queues
#define TX_entries 60		//UART transmit buffer 59 Byte (max. size + 1)		
#define RX_entries 60		//UART receive buffer 59 Byte (max. size + 1)
//*************** Globale Variablen ****************************
CANI_qentrytyp rcv_queue[QUEUE_RCV_SIZE];	
CANI_qentrytyp xmt_queue[QUEUE_XMT_SIZE];	

u8_t Buf_XMTQueue[TX_entries];
u8_t Buf_RCVQueue[RX_entries];
//***********************************************************************

void Timer_2000Hz()
{
	static u8_t n;

	UDC_Server();
	n++;
	if(n&1)	// nur jedes 2. mal aufrufen
	{
		LED_1000Hz();
		AD_1000Hz();
	}
}

//*************************************************************
static void Eval_CANFrames()
{
	if(CAN_Read()==CAN_ERR_OK)	// if an new CAN-Message was received
	{
		switch(CAN_BUFF_ID)
		{
			// Firmwareupdate via CAN
			//convert x.mhx into x.bin via mot2bin.exe (see ...\Release\ABS) and upload with CAN2Flash.exe to MicroMod  
			case 0x7e7:
/* 
The Library-Funktion  CAN_Read() fills the variables CAN_BUFF_ID, CAN_BUFF_LEN, CAN_BUFF_DATA[8] with the last Queue-entry of the CAN-message.
When using own CAN-LowLevel drivers must befor call the function mCAN_EvalInitialCmd() the variables
CAN_BUFF_ID
CAN_BUFF_LEN
CAN_BUFF_DATA[8]
be filled with the CAN-data.

*/
				// all outputs off
				Set_DOUTByte(0);
								
				mCAN_EvalInitialCmd();			
			break;
	//process other CAN-ID 
			default:
			break;
		} // switch
		
	} // if(CAN_Read()=...
}

//*************************************************************

void main()
{
	u16_t delay=0;
	u8_t index=0;
	
	InitIrqLevels();
    __set_il(7);		// allow all levels 

	Hardware_Init();
	Timer_Init();

	CAN_SetRCVQueue(rcv_queue, QUEUE_RCV_SIZE);	// Set Receive Queue to 8 entries, 
	CAN_SetXMTQueue(xmt_queue, QUEUE_XMT_SIZE);	// Set CAN Transmit Queue to 8 entries
	CAN_Init(CAN_BAUD_500K);
	CAN_RegisterMsg(0);
	CAN_Online();
	
	Timer_Set(0, 50) ;
	Timer_Set(1, 500) ;
	
	// This function call initializes a incremental input for DIN0 and DIN1. (channel 0)
	// After Power-On the Start-value is set to 10.
	// Minimum value of the counter is 5 maximum value is 15.
	// When counting up, the counter rolls over from 15 to 5, counting down rolls over from 5 to 15
	UDC_Init( /*uchar channel*/0, /*word initval*/10, /*word loval*/ 5, /*word hival*/ 15, /*uchar mode*/UDC_ROLL_OVER);

	// This function call initializes a incremental input for DIN2 and DIN3. (channel 1)
	// After Power-On the Start-value is set to 18.
	// Minimum value of the counter is 15 maximum value is 28.
	// When counting up, the counter stays at the max. value of 28.
	// When counting down, the counter stays at the min. value of 15.
	// During runtime the Function "UDC_GetCount(uchar channel) ;" is used to get the current counter value.
	UDC_Init( /*uchar channel*/1, /*word initval*/18, /*word loval*/ 15, /*word hival*/ 28, /*uchar mode*/0);

	// This function call initializes a incremental input for DIN4 and DIN5. (channel 2)
	// During runtime the Function "UDC_GetDelta(uchar channel)" is used to get the
	// change in counts since the last function call.
	// For this mode it is required to set the minvalue to 0 and the maxvalue to 65535.
	// Return value is a signed integer.(-1=0xffff, 1=0x0001
	UDC_Init( /*uchar channel*/2, /*word initval*/0, /*word loval*/ 0, /*word hival*/ 65535, /*uchar mode*/UDC_ROLL_OVER);

	__EI();				// Enable Interrupts
	
	for(;;)							//Main_loop
	{	
		Eval_CANFrames();		//call CAN receive function
		WATCHDOG;
		
		if(CAN_Status()== CAN_ERR_BUSOFF)
		{
			CAN_Online();
		}

		if(CAN_Read()==CAN_ERR_OK)
		{
			CAN_Write();
		}
		
		if(Timer(0)==0)
		{
			Timer_Set(0, 50) ; // repeat message every 50 Milliseconds
			CAN_BUFF_ID=0x223;	// Message with counter values 
			CAN_BUFF_LEN=2;
			CAN_BUFF_DATA[0]=UDC_GetCount(0);
			CAN_BUFF_DATA[1]=UDC_GetCount(1);
			CAN_BUFF_FORMAT = CAN_EXT;	// extended 29 bit
			CAN_BUFF_INDEX=index;	// return-value of Tx complete callback
			CAN_Write();
			index++;
		}
		
		if(Timer(1)==0)
		{
			Timer_Set(1, 500) ; // repeat message every 500 Milliseconds
			CAN_BUFF_ID=0x224;	// Message with counter-difference
			CAN_BUFF_LEN=1;
			CAN_BUFF_DATA[0]=UDC_GetDelta(2);
			CAN_BUFF_FORMAT = CAN_EXT;	// extended 29 bit
			CAN_BUFF_INDEX=index;	// return-value of Tx complete callback
			CAN_Write();
			index++;
		}
	} //for_ever loop
}