//----------------------------------------------------
/**
	\file		atsam4e16e/inc/twim.h
	\ingroup	hardware
	\ingroup	cortex-m4

	\brief		Knihovna pro ovladani TWI (i2c) interface v master rezimu
				<<< CORTEX M4 >>>

	\author		ConTeK s.r.o., Ing. Petr Cernin, Bc. Jan Prasil
	\version	01.01
	\date		12.01.2007
*/
//----------------------------------------------------


#ifndef _TWIM_H_
#define _TWIM_H_		//!< Definice pritomnosti knihovny

#include <libsets.h>
#include <ctktypes.h>

//----------------------------------------------------
//!	\name	Konstanty definujici status transakci
//@{

#define TWS_SUCCESS			0	//!< Transakce byla uspesne dokoncena
#define TWS_PENDING			1	//!< Transakce probiha
#define TWS_WAITING			2	//!< Transakce ceka na zpracovani
#define TWS_BUS_ERROR		3	//!< Chyba sbernice
#define TWS_NACK			4	//!< Nepotvrzena data
#define TWS_UNDERFLOW		5	//!< Software nestihl vcas obslouzit preruseni
#define TWS_BADFORMAT		6	//!< Data nelze prenest (krizici se pozadavek na vysilani a prijem, dlouha adresa...)
#define TWS_VERIFY_ERROR	7	//!< Chyba pri porovnavani obsahu bufferu s prijatymi daty
#define TWS_INTERNAL_ERROR	8	//!< Vnitrni chyba (napr. u ARM zavolano IRQ, kdyz se melo volat FIQ)
//@}


//#define TWI_MAX_CHANNELS	3	//!< Pocet definovanych TWI kanalu !>Pr Presunuto do libsets.h


//----------------------------------------------------
/**
	\brief	Callback typ volany po dokonceni transakce

	\param	status		Vysledek transakce (viz TWS_*)
	\param	userData	Uzivatelska data
*/
//----------------------------------------------------

typedef void (* twiCallback_t) (uint8_t _status, void * _userData);


//----------------------------------------------------
/**
	\brief	Typ delky prenasenych dat
*/
//----------------------------------------------------

typedef uint16_t twisize_t;

//!---------------------------------------------------
//! \name	Forward deklarace
//@{
union _TWIUSERBYTES;
struct _TWIDESC;
//@}

//!----------------------------------------------------
//!	\brief	Typy metod pouzivanych jako komunikacni rozhrani knihovny
//!			Zarizeni vyuzivajici TWI, by meli vyuzivat toto rozhrani,
//!			ktere bude implementovano do TWIDESC.
//!
//!	\note	Uprava z duvodu implementace SW TWI. Duvodem upravy, je
//!			jedno spolecene rozhrani TWI, kde nebude zalezet na
//!			fyzicke vrstve.
//!
//!	\todo	Predelat zpusob volani transakci u knihoven vyuzivajici TWI.
//!			(Zatim bude predelana FRAM a RTC)
//@{

//----------------------------------------------------
/**
	\brief	Funkce pro provedeni jednoduche transakce na sbernici

	\param	twiD	struktura kontextu automatu
	\param	channel	cislo komunikacniho kanalu (0 .. TWI_MAX_CHANNELS - 1)
	\param	slave	Adresa slave jednotky na sbernici
	\param	txData	Ukazatel na vysilana data
	\param	txSize	Delka vysilanych dat
	\param	rxData	Ukazatel na buffer pro prijem
	\param	rxSize	Delka prijimanych dat

	\note	Funkce se vrati okamzite. Transakce se dokonci v preruseni.
			Dokonceni transakce lze testovat funkcemi
			twiReady() prip. twiStatus()
			slave	- M41T81	0x68
					- F24C16	0x50 + (Addr >> 8) & 0x07
			V callbacku neni zajistena reentrance systemovych knihoven
*/
//----------------------------------------------------
typedef void (* twiTransact_t)(struct _TWIDESC * const _twiD, const uint8_t _channel, const uint8_t _slave,
		const void * const _txData, const twisize_t _txSize,
		void * const _rxData, const twisize_t _rxSize,
		twiCallback_t _callback, void * const _userData);

//----------------------------------------------------
/**
	\brief	Funkce pro provedeni rozsirene transakce na sbernici

	\param	twiD	struktura kontextu automatu
	\param	channel	cislo komunikacniho kanalu (0 .. TWI_MAX_CHANNELS - 1)
	\param	slave	Adresa slave jednotky na sbernici
	\param	txDataA	Ukazatel na vysilana data A
	\param	txSizeA	Delka vysilanych dat A
	\param	txDataB	Ukazatel na vysilana data B
	\param	txSizeB	Delka vysilanych dat B
	\param	rxData	Ukazatel na buffer pro prijem
	\param	rxSize	Delka prijimanych dat

	\note	Funkce se vrati okamzite. Transakce se dokonci v preruseni.
			Dokonceni transakce lze testovat funkcemi
			twiReady() prip. twiStatus()
			V callbacku neni zajistena reentrance systemovych knihoven
*/
//----------------------------------------------------
typedef void (* twiTransactEx_t)(struct _TWIDESC * const _twiD, const uint8_t _channel, const uint8_t _slave,
	const void * const _txDataA, const twisize_t _txSizeA,
	const void * const _txDataB, const twisize_t _txSizeB,
	void * const _rxData, const twisize_t _rxSize,

#ifdef TWI_COMPARE
	const bool_t _compare,
#endif

	twiCallback_t _callback, void * const _userData);

//----------------------------------------------------
/**
	\brief	Funkce pro provedeni inicializace radice sbernice i2c
			a provedeni inicializace automatu

	\param	twiD	struktura kontextu automatu
*/
//----------------------------------------------------
typedef void (* twiReset_t)(struct _TWIDESC * const _twiD);

//----------------------------------------------------
/**
	\brief	Funkce  testuje, zda komunikacni kanal dokoncil predchozi
			transakci a je schopen provest dalsi

	\param	twiD	struktura kontextu automatu
	\param	channel	cislo komunikacniho kanalu (0 .. TWI_MAX_CHANNELS - 1)

	\return	Vraci nenulovou hodnotu, pokud byla predchozi transakce dokoncena
*/
//----------------------------------------------------
typedef bool_t (* twiReady_t)(const struct _TWIDESC * const _twiD, const uint8_t _channel);

//----------------------------------------------------
/**
	\brief	Funkce vraci status naposledy dokoncene transakce

	\param	twiD	struktura kontextu automatu
	\param	channel	cislo komunikacniho kanalu (0 .. TWI_MAX_CHANNELS - 1)

	\return	Vraci jednu z konstant TWS_xxx.
			Pokud transakce nebyla dokoncena, vraci TWS_PENDING.
*/
//----------------------------------------------------
typedef uint8_t (* twiStatus_t)(const struct _TWIDESC * const _twiD, const uint8_t _channel);

//----------------------------------------------------
/**
	\brief	Funkce vraci ukazatel na uzivatelske bajty kanalu

	\param	twiD	struktura kontextu automatu
	\param	channel	cislo komunikacniho kanalu (0 .. TWI_MAX_CHANNELS - 1)

	\return	Vraci ukazatel na dva volne bajty, ktere muze
			volajici pouzit k libovolnemu ucelu
*/
//----------------------------------------------------
typedef union _TWIUSERBYTES * (* twiUserBytes_t)(struct _TWIDESC * const _twiD, const uint8_t _channel);
//@}


typedef union _TWIUSERBYTES
{
	struct
	{
		uint8_t	b0;
		uint8_t	b1;
	};

	uint16_t w0;

} TWIUSERBYTES;


#ifdef TWI_COMPARE
//----------------------------------------------------
/**
	\brief	Typ vyjadrujici stav operace porovnavani
*/
//----------------------------------------------------

typedef enum _TWICMP_STATUS
{
	TWICMP_DISABLED,		//!< Neporovnava se
	TWICMP_ENABLED,		//!< Porovnava se
	TWICMP_FAILED			//!< Detekovana chyba pri porovnavani
} TWICMP_STATUS;

#endif // TWI_COMPARE

//----------------------------------------------------
//!	Struktura kanalu TWI

typedef struct
{
	volatile uint8_t Status;		//!< Status kanalu TWS_xxx

	uint8_t			Slave;		//!< Adresa na i2c

	const uint8_t	*TxDataA;	//!< Vysilana data A
	twisize_t		TxSizeA;	//!< Delka vysilanych dat A

	const uint8_t	*TxDataB;	//!< Vysilana data B
	twisize_t		TxSizeB;	//!< Delka vysilanych dat B

	uint8_t	*		RxData;		//!< Prijimana data
	twisize_t		RxSize;		//!< Delka prijimanych dat

	twiCallback_t	Callback;	//!< Callback volany pri dokonceni TWI transakce
	void *			UserData;	//!< Uzivatelska data, ktera budou callbacku predana

#ifdef TWI_COMPARE
	TWICMP_STATUS	Compare;	//!< Namisto prijmu se provadi porovnavani prijatych dat
#endif // TWI_COMPARE

	TWIUSERBYTES	User;		//!< Uzivatelske promenne
	uint8_t			RWFlag;

} TWICHANNEL;


//----------------------------------------------------
//!	Struktura kontextu automatu

typedef struct _TWIDESC
{
	volatile bool_t	flRunning;		//!< je inicializovano, po ininializaci na TRUE, pred ukoncenim FALSE
	volatile bool_t	Busy;			//!< Priznak probihajici transakce
	uint8_t			Channel;		//!< Cislo aktualne obsluhovaneho kanalu
	uint8_t			Number;			//!< Cislo Twi

	//!Implementace noveho rozhrani
	twiTransact_t	TwiTransact;
	twiTransactEx_t	TwiTransactEx;
	twiReset_t		TwiReset;
	twiReady_t		TwiReady;
	twiStatus_t		TwiStatus;
	twiUserBytes_t	TwiUserBytes;

	TWICHANNEL 		Channels[TWI_MAX_CHANNELS];

} TWIDESC;


//----------------------------------------------------
/**
	\brief	Funkce pro provedeni inicializace radice sbernice i2c
			a provedeni inicializace automatu

	\param	twiD	struktura kontextu automatu

	\return	TRUE	inicializace probehla v poradku
			FALSE	chyba
*/
//----------------------------------------------------

bool_t TwiInitialize(TWIDESC * const _twiD, uint8_t _number);


//----------------------------------------------------
/**
	\brief	Funkce pro ukonceni cinnosti radice sbernice i2c

	\param	twiD	struktura kontextu automatu
*/
//----------------------------------------------------

void TwiFinalize(TWIDESC * const _twiD);

#endif // #ifndef _TWIM_H_
