//----------------------------------------------------
/**
	\file		ctk/inc/j1939.h
	\ingroup	can
	\ingroup	all

	\brief		Implementace protokolu  SAE/J1939
				<<< ALL >>>

	\author		ConTeK s.r.o., Pavel Bazika
	\version	01.01
*/
//----------------------------------------------------

#ifndef J1939_H_
#define J1939_H_

#include <libsets.h>
#include <cancomm.h>
#include <hwmodel.h>

//----------------------------------------------------
//!	\name	Stavy bufferu J1939
//@{

#define		JSTS_NREADY_FLAG		0x80		//!< Priznak, ze buffer neni pripraven

// stavy pripravenosti
#define		JSTS_READY				0x00		//!< Obecny stav pripravenosti bufferu
#define		JSTS_RECEIVED			0x01		//!< Prijimaci buffer naplnen
#define		JSTS_SENT				0x02		//!< Vysilaci buffer odeslan
#define		JSTS_ERROR				0x40		//!< Doslo k chybe

// stavy nepripravenosti
#define		JSTS_PENDING			(0x04 | JSTS_NREADY_FLAG)	//!< Buffer obsazen
#define		JSTS_FILLING			(0x08 | JSTS_NREADY_FLAG)	//!< Buffer je plnen
#define		JSTS_WAITING			(0x10 | JSTS_NREADY_FLAG)	//!< Buffer ceka na odeslani
#define		JSTS_SENDING			(0x20 | JSTS_NREADY_FLAG)	//!< Buffer se prave odesila

#define J1939_ADDR_NULL			254
#define J1939_ADDR_ALL			255
//@}

//----------------------------------------------------
//	\brief	Kontrola, zda je knihovna pripravena k vysilani

/*#define J1939BufSendReady(ctx) \
	BufDescReady((ctx)->LastSendDesc->Status == STS_READY)*/


//----------------------------------------------------
/**
//	\brief	Ziskani casti ID
*/
//----------------------------------------------------

static uint8_t J1939PGN2Datapage(const uint32_t PGN) _const;
static inline uint8_t J1939PGN2Datapage(const uint32_t PGN)
{
	return (PGN >> 16) & 0x01;
}

static uint8_t J1939PGN2PF(const uint32_t PGN) _const;
static inline uint8_t J1939PGN2PF(const uint32_t PGN)
{
	return (PGN >> 8) & 0xFF;
}

static uint8_t J1939PGN2PS(const uint32_t PGN) _const;
static inline uint8_t J1939PGN2PS(const uint32_t PGN)
{
	return PGN & 0xFF;
}

static uint8_t J1939PGN2GE(const uint32_t PGN) _const;
static inline uint8_t J1939PGN2GE(const uint32_t PGN)
{
	if (J1939PGN2PF(PGN) >= 0xF0)
	{
		return J1939PGN2PS(PGN);
	}
	else {
		return 0x00;
	}
}

static uint32_t J1939CreatePGN(const uint8_t DP, const uint8_t PF, const uint8_t PS) _const;
static inline uint32_t J1939CreatePGN(const uint8_t DP, const uint8_t PF, const uint8_t PS)
{
	return (DP << 16) | (PF << 8) | ((PF >= 0xF0) ? PS : 0);
}

//----------------------------------------------------
//! libsets - maximalni pocet soucasne prijimanych bcastu
#define	J1939_BCAST_THREAD_MAX		4

//----------------------------------------------------
//! libsets - maximalni pocet soucasne prijimanych P2P
#define J1939_P2P_THREAD_MAX		4

//----------------------------------------------------
//! libsets - maximalni pocet soucasne vysilanych p2p
#ifdef MIB01B
 #define J1939_P2P_SEND_THREAD_MAX	4
#else
 #define J1939_P2P_SEND_THREAD_MAX	2
#endif //MIB01B
/*// libsets - regulace pridavani novych threadu p2p, cim vyssi hodnota, tim mene threadu
#define J1939_P2P_SEND_BUSY			100
*/

//-----------------------------------------------------
//! pocet vysilacich bufferu
#ifdef MIB01B
 #define HCAN_SENDBUF_COUNT	5U
#else
 #define HCAN_SENDBUF_COUNT	1U
#endif //MIB01B


//-----------------------------------------------------
// pocet univerzalnich prijimacich bufferu
#define HCAN_RECVBUF_COUNT	6U

#ifdef J1939_MULTI_P2P
//! pocet paketu potvrzovanych CTS
	#define	J1939_P2P_CTS_COUNT		1
#endif // J1939_MULTI_P2P

//----------------------------------------------------
//!	Typ delky zpravy J1939

typedef uint16_t	J1939_MSGSIZE;


//----------------------------------------------------
//! Protokoly J1939
typedef enum _J1939_PROTOCOL
{
	JP_BCAST,
	JP_P2P
} J1939_PROTOCOL;

//----------------------------------------------------
//!	Stavy vysilaciho automatu

typedef enum _J1939_MULTI_BCASTSEND
{
	JBS_START = 0,
	JBS_BCASTDONE,
	JBS_SENDSIMPLEBCAST,
	JBS_BCASTPAUSE

#ifdef J1939_MULTI_BCAST
	,JBS_SENDBAM,
	JBS_WAITSENT,
	JBS_WAITDELAY,
	JBS_SENDDT
#endif // J1939_MULTI_BCAST

} J1939_MULTI_BCASTSEND;


//----------------------------------------------------
//!	Struktura ID J1939

typedef struct _J1939_ID
{
	uint8_t 	Priority;
	uint8_t		DataPage;
	uint8_t		PF;
	uint8_t		PS;
	uint8_t		SA;
} J1939_ID;


//----------------------------------------------------
//!	Buffer CAN zpravy pro J1939

typedef struct _J1939_CANMSG
{
	uint8_t		Size;
	J1939_ID	ID;
	uint8_t		MsgData[8];
} J1939_CANMSG;


//----------------------------------------------------
//!	\brief	Buffer zpravy J1939

typedef struct _J1939_BUFFER
{
	struct _J1939_BUFFER 	*Next;		//!< Ukazatel na nasledujici deskriptor ve fronte
	status_t		Status;				//!< Stav bufferu
	uint16_t		Size;				//!< Velikost dat, ktera buffer pojme
	uint16_t		UsedSize;			//!< Velikost dat, ktera buffer obsahuje
	uint32_t		FilterID;			//!< Specifikace urceni bufferu
	uint32_t		FilterMask;			//!< Specifikace urceni bufferu
	J1939_PROTOCOL	Protocol;			//!< Protokol, kterym je buffer prenasen
	uint8_t			Priority;			//!< Priorita zpravy J1939
	uint8_t			DataPage;			//!< Datapage zpravy J1939
	uint8_t			PF;					//!< PDU format zpravy J1939
	uint8_t			PS;					//!< PDU specific zpravy J1939
	uint8_t			DestAddress;		//!< Adresa cilova
	uint8_t			SourceAddress;		//!< Adresa zdrojova
	void *			MsgData;			//!< Vlastni data
} J1939_BUFFER;


//----------------------------------------------------
//!	Status prijimace broadcastu

typedef enum _J1939_THREAD_STATUS
{
	JTS_PASSIVE,
	JTS_ACTIVE
} J1939_THREAD_STATUS;


#ifdef J1939_MULTI_P2P

//----------------------------------------------------
//!	Status prijimace broadcastu

typedef enum _J1939_RECV_STATE
{
	JRS_START = 0,
	JRS_SENDCTS,
	JRS_WAITDT,
	JRS_RECVDT,
	JRS_SENDEOMA,
	JRS_SENDABORT,
	JRS_EXITTHREAD,
	JRS_STOPPED
} J1939_RECV_STATE;

#endif // J1939_MULTI_P2P


//----------------------------------------------------
//!	Kontext prijimaciho automatu

typedef struct _J1939_RECV_THREAD_CTX
{
	J1939_THREAD_STATUS	Status;

#if defined(J1939_MULTI_BCAST) || defined(J1939_MULTI_P2P)
	J1939_PROTOCOL		Protocol;
	ticks_t				Timer;

	uint8_t				SeqNumber;

	uint8_t				SrcAddr;
	uint16_t			Size;
	uint8_t				PacketCount;
	uint8_t				DataPage;
	uint16_t			PGN;

	J1939_BUFFER		* DestBuf;
	uint8_t 			* DestPtr;

	CAN_BUFFER			TransmitBuf;
#endif // J1939_MULTI_BCAST || J1939_MULTI_P2P

#ifdef J1939_MULTI_P2P
	J1939_RECV_STATE	RecvState;
	bool_t				Pause;
	uint8_t				Expect;
	uint8_t				RetryCount;
#endif // J1939_MULTI_P2P

} J1939_RECV_THREAD_CTX;


//----------------------------------------------------
//!	\brief	Status prijimace broadcastu

typedef enum _J1939_SEND_STATE
{
	JSS_START = 0,
	JSS_EXITTHREAD,
	JSS_P2PPAUSE

#ifdef J1939_MULTI_P2P
	,JSS_WAITPRECTSSENT,
	JSS_WAITCTSRECV,
	JSS_SENDABORT,
	JSS_SENDDT,
	JSS_REPEATLAST,
	JSS_STOPPED,
	JSS_WAITLASTSENT,
	JSS_WAITEOMA
#endif // J1939_MULTI_P2P

} J1939_SEND_STATE;


//----------------------------------------------------
//!	Status address claim

#ifdef J1939_ADDRESSCLAIM

typedef enum _J1939_ACSTATE
{
	JAS_START = 0,
	JAS_WAIT,
	JAS_REJECT,
	JAS_SENDCANNOT,
	JAS_SENDCANNOT_WBUF,
	JAS_NOTHING
} J1939_ACSTATE;

#endif // J1939_ADDRESSCLAIM


//----------------------------------------------------
//!	Typ ACK

typedef enum _J1939_ACKTYPE
{
	JAT_POSITIVE = 0,
	JAT_NEGATIVE = 1,
	JAT_DENIED = 2,
	JAT_CANTRESP = 3
} J1939_ACKTYPE;


//----------------------------------------------------
//!	Kontext vysilaciho automatu P2P

typedef struct _J1939_SEND_THREAD_CTX
{
	volatile J1939_THREAD_STATUS	Status;
	volatile J1939_SEND_STATE	State;

	CAN_BUFFER				TransmitBuf;

	J1939_BUFFER *			SrcBuf;
	const uint8_t *			SrcData;

	unsigned				RetryCount;
	ticks_t					Timer;

#ifdef J1939_MULTI_P2P
	uint8_t					TotalPackets;
	uint8_t					PacketCount;
	uint8_t					SeqNumber;
#endif // J1939_MULTI_P2P

} J1939_SEND_THREAD_CTX;

//----------------------------------------------------
//!	\brief	Chybove kody J1939

typedef enum _J1939_ERRCODE
{
	JEC_NONE

#if defined(J1939_MULTI_BCAST) || defined(J1939_MULTI_P2P) || defined(J1939_PROPRIETARY_P2P) || defined(J1939_PROPRIETARY_BCAST)
	,JEC_DISCARD			//!< Prijaty paket bude zahozen
#endif // J1939_MULTI_BCAST || J1939_MULTI_P2P

#if !defined(J1939_MULTI_BCAST) || !defined(J1939_MULTI_P2P)
	,JEC_MULTIPACKET		//!< Pokus o odeslani multipaketu, coz neni podporovano
#endif

#ifdef J1939_MULTI_BCAST
	,JEC_BCAST_ABORT,		//!< Broadcast zrusen vysilaci stranou
	JEC_BCAST_TIMEOUT,		//!< Nedorazila dalsi zprava v limitu
	JEC_BCAST_FULL,			//!< Ve fronte prijimanych broadcastu jiz neni misto pro dalsi
	JEC_BCAST_RUNNING		//!< Oznameny broadcast jiz probiha
#endif // J1939_MULTI_BCAST

#ifdef J1939_MULTI_P2P
	,JEC_P2P_BADCTS,			//!< Prijemce odeslal nespravne CTS a vyprsel pocet pokusu o odeslani
	JEC_P2P_TIMEOUT,		//!< Vyprsel timeout mezi pakety vysilace a vsechny pokusy o opakovani
	JEC_P2P_BADEOMA,		//!< Zaverecny paket obsahoval nespravne udaje
	JEC_P2P_ABORT,			//!< spojeni ukonceno druhou stranou
	JEC_P2P_RUNNING,		//!< Navazovane spojeni je jiz navazano a probiha
	JEC_P2P_FULL,			//!< Thread P2P neni k dispozici
	JEC_P2P_STOP_TIMEOUT	//!< Vyprsel limit pro prodlouzeni pozastaveneho spojeni*/
#endif // J1939_MULTI_P2P
} J1939_ERRCODE;


//----------------------------------------------------
//!	Stav J1939

typedef enum _J1939_RUNLEVEL
{
	JRL_NOINIT = 0,
	JRL_INIT,
	JRL_RUNNING

#ifdef J1939_ADDRESSCLAIM
	,JRL_CLAIMING,
	JRL_CANNOTCLAIM
#endif // J1939_ADDRESSCLAIM

} J1939_RUNLEVEL;


struct _J1939_CTX;

//----------------------------------------------------
//!	\name	Callbacky
//@{

typedef void (*jmNoResponse) (const struct _J1939_CTX * const ctx, const J1939_BUFFER * const buf);

typedef void (*jmPGNRequest) (const struct _J1939_CTX * const ctx, const uint32_t PGN);

typedef void (*jmError) ( const struct _J1939_CTX * const ctx, const J1939_ERRCODE errcode);

typedef void (*jmReceived) ( struct _J1939_CTX * const ctx, const J1939_BUFFER * const msg );

typedef void (*jmSent) ( const struct _J1939_CTX * const ctx, const J1939_BUFFER * const msg );

typedef void (*jmClaimDone) ( const struct _J1939_CTX * const ctx, const uint8_t Address);

typedef void (*jmClaimError) ( const struct _J1939_CTX * const ctx, const uint8_t Address, const uint64_t LooserName);


#ifdef J1939_FLOWCONTROL
typedef uint8_t (*jmNextPacketCount) ( const struct _J1939_CTX * const jctx, const J1939_RECV_THREAD_CTX * const ctx);

typedef bool_t (*jmAcceptConnection) ( const struct _J1939_CTX * const jctx, const J1939_CANMSG * const rts);
#endif // J1939_FLOWCONTROL

#ifdef J1939_REQUEST

typedef bool_t (*jmRequestRecv) ( struct _J1939_CTX * const jctx, const uint32_t PGN, const uint8_t SrcAddr);

typedef bool_t (*jmAckRecv) ( const struct _J1939_CTX * const jctx, const J1939_CANMSG * const msg );

#endif // J1939_REQUEST
//@}

//----------------------------------------------------
//!	\brief	Kontext J1939

typedef struct _J1939_CTX
{
	CANDEVICE		Device;						//!< Struktura CAN zarizeni (predek)

	CANCOMMDESC * 	cmm;					//!< Odkaz na CAN komunikaci

	uint8_t 		Address;				//!< Adresa v siti J1939

	//!	\name Vysilaci buffery J1939
	//@{
	// FULL -- FULL -- FULL -- FREE -- FREE -- FREE -- FREE
	// first                   free                    last

	J1939_BUFFER *	FirstSendDesc;
	J1939_BUFFER *	LastSendDesc;
	//@}

	//! \name Prijimaci buffery J1939
	//@{

	J1939_BUFFER *	FirstRecvDesc;
	J1939_BUFFER *	LastRecvDesc;
	//@}

	//! \name Broadcast vysilani
	//@{

	J1939_BUFFER *	BCastBuf;
	const uint8_t *	BCastData;
	J1939_MULTI_BCASTSEND	BCastState;
	CAN_BUFFER		BCastTransmitBuf;

#ifdef J1939_MULTI_BCAST
	uint8_t			BCastPacketCount;
	uint8_t			BCastSeqNumber;
	//todo - proc tu je duplicitne ticks_t			BCastTimer;
	//@}

	//!	\name Broadcast prijem
	//@{

	J1939_RECV_THREAD_CTX	BCastRecvFSM[J1939_BCAST_THREAD_MAX];
	unsigned				BCastRecvLastActive;
	//@}
#endif // J1939_MULTI_BCAST

#ifdef J1939_MULTI_P2P
	//! P2P prijem
	J1939_RECV_THREAD_CTX	P2PRecvFSM[J1939_P2P_THREAD_MAX];
	unsigned				P2PRecvLastActive;
#endif // J1939_MULTI_P2P

	//! P2P vysilani
	J1939_SEND_THREAD_CTX	P2PSendFSM[J1939_P2P_SEND_THREAD_MAX];
	unsigned				P2PSendLastActive;
	unsigned				P2PSendActiveCount;


#ifdef J1939_ADDRESSCLAIM
	//! \name Address claim
	//@{
	// vyuziva broadcast buffer
	J1939_ACSTATE	ClaimState;
	ticks_t			ClaimTimer;
	uint8_t			ClaimedAddr;
	uint64_t		Name;					//!< Jednoznacny id ecu
	//@}
#endif // J1939_ADDRESSCLAIM

	//!	\name Callbacky
	//@{

	jmNoResponse	cbNoResponse;
	jmPGNRequest	cbPGNRequest;
	jmError			cbError;
	jmReceived		cbReceived;				//!< Volano pri prijmu zpravy
	jmSent			cbSent;					//!< Volano pri odvysilani zpravy

#ifdef J1939_ADDRESSCLAIM
	jmClaimError	jmiClaimError;
	jmClaimDone		jmiClaimDone;
#endif // J1939_ADDRESSCLAIM
	//@}

#ifdef J1939_FLOWCONTROL
	jmNextPacketCount	jmiNextPacketCount;
	jmAcceptConnection	jmiAcceptConnection;
#endif // J1939_FLOWCONTROL

#ifdef J1939_REQUEST
	jmRequestRecv		cbRequestRecv;
	jmAckRecv			cbAckRecv;
#endif // J1939_REQUEST

	J1939_RUNLEVEL 	RunLevel;				//!< Priznak uspesne inicializace

	ticks_t			BCastPause;
	ticks_t			BCastTimer;

	ticks_t			P2PPause;
	ticks_t			P2PTimer;

	CAN_BUFFER		AbortBuf;				//!< Buffer pro odesilani abortu

} J1939_CTX;

//----------------------------------------------------
/**
	\brief	Zjisteni pripravenosti J1939 pro vysilani P2P zprav
*/
//----------------------------------------------------

static inline bool_t J1939BufReady(const J1939_BUFFER * const _buf)
{
	const J1939_BUFFER *temp_p = _buf;

	for(unsigned n = 0; n < HCAN_SENDBUF_COUNT; n++)
	{
		if(temp_p[n].Status == JSTS_READY || temp_p[n].Status == JSTS_SENT)
		{
			return TRUE;
		}

	}
	return FALSE;
}


//----------------------------------------------------
/**
	\brief	Vrátí volný J1939_BUFFER pro vysilani
*/
//----------------------------------------------------

static inline J1939_BUFFER* J1939GetFreeSendBuf(const J1939_BUFFER * const _buf)
{
	const J1939_BUFFER * temp_p = _buf;

	for(unsigned n = 0; n < HCAN_SENDBUF_COUNT; n++)
	{
		if(temp_p[n].Status == JSTS_READY || temp_p[n].Status == JSTS_SENT)
		{
			return (J1939_BUFFER*) &temp_p[n];
		}
	}

	return NULL;
}

//----------------------------------------------------
/**
	\brief	Oznaci buffer jako uvolneny
*/
//----------------------------------------------------

static inline void J1939RecvBuffFree(J1939_BUFFER * const Buf)
{
	AtomWrite(Buf->Status, JSTS_READY);
}



//----------------------------------------------------
/**
		\brief	Konverze struktury na ID
*/
//----------------------------------------------------
uint32_t J1939IDStruct2Bin(const J1939_ID * const id);

//----------------------------------------------------
/**
	\brief	Konverze ID na strukturu
*/
//----------------------------------------------------
const J1939_ID * J1939Bin2IDStruct(J1939_ID * const dest, const uint32_t src);

void J1939BuffPrepare(const J1939_CTX * const jctx, J1939_BUFFER * const Buf, void * const MsgData, const J1939_MSGSIZE Size);


void J1939RecvBuffEnqueue(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint32_t FilterID,
		const uint32_t FilterMask);

void J1939SendBuffEnqueue(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint32_t FilterID,
		const uint32_t FilterMask);



//----------------------------------------------------
/**
   \brief Vyjme J1939_BUFFER z fronty a nastavi jeho status na JSTS_READY
 */
//----------------------------------------------------

void inline J1939SendBuffDequeue(J1939_CTX * const jctx, J1939_BUFFER * const Buf)
{
	flock_t lock = FastLock();
	J1939_BUFFER* temp_Buf;

	if(Buf->Next == NULL)
	{
		if(Buf == jctx->FirstSendDesc)
		{
			jctx->FirstSendDesc = jctx->LastSendDesc = NULL;
		}
		else
		{
			temp_Buf = jctx->FirstSendDesc;
			while(temp_Buf->Next != Buf)
			{
				temp_Buf = temp_Buf->Next;
			}
			jctx->LastSendDesc = temp_Buf;
			temp_Buf->Next = Buf->Next;
		}
	}
	else
	{
		if(Buf == jctx->FirstSendDesc)
		{
			jctx->FirstSendDesc = Buf->Next;
		}
		else
		{
			temp_Buf = jctx->FirstSendDesc;
			while(temp_Buf->Next != Buf)
			{
				temp_Buf = temp_Buf->Next;
			}
			temp_Buf->Next = Buf->Next;
		}
	}

	Buf->Status = JSTS_READY;
	FastUnlock(lock);
}

//----------------------------------------------------
/**
	\brief	Zmeni adresu zarizeni
*/
//----------------------------------------------------
void J1939SetAddress(J1939_CTX * const jctx, const uint8_t Address);

uint8_t inline J1939GetAddress(J1939_CTX * const jctx)
{
	return jctx->Address;
}

//----------------------------------------------------
/**
	\brief	Umozni odvysilat zpravu s nestandarni adresou odesilatele
*/
//----------------------------------------------------
bool_t J1939SendSourceMsg(J1939_CTX * const jctx, J1939_BUFFER * Buf, const J1939_PROTOCOL Protocol,
		const uint8_t DestAddr, const uint8_t SourceAddr, const uint8_t Priority, const uint8_t DataPage, const uint8_t PF, const uint8_t PS,
		const void * const Data, const J1939_MSGSIZE Size);

bool_t inline J1939SendMsg(J1939_CTX * const jctx, J1939_BUFFER * Buf, const J1939_PROTOCOL Protocol,
		const uint8_t DestAddr, const uint8_t Priority, const uint8_t DataPage, const uint8_t PF, const uint8_t PS,
		const void * const Data, const J1939_MSGSIZE Size)
{
	return J1939SendSourceMsg(jctx, Buf, Protocol,
			DestAddr, J1939GetAddress(jctx), Priority, DataPage, PF, PS,
			Data, Size);
}


//----------------------------------------------------
/**
	\brief	Odeslani broadcast zpravy
*/
//----------------------------------------------------
bool_t J1939SendBCastMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t Priority,
		const uint8_t DataPage, const uint8_t PF, const uint8_t PS, const void * const Data, const J1939_MSGSIZE Size);


//----------------------------------------------------
/**
	\brief	Odeslani p2p zpravy
*/
//----------------------------------------------------
bool_t J1939SendP2PMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t DestAddr,
		const uint8_t Priority, const uint8_t DataPage, const uint8_t PF, const void * const Data, const J1939_MSGSIZE Size);

//	Odeslani prop A zpravy
#ifdef J1939_PROPRIETARY_P2P
bool_t J1939SendPropP2PMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t DestAddr,
		const uint8_t Priority, const uint8_t DataPage, const void * const Data, const J1939_MSGSIZE Size);
#endif // J1939_PROPRIETARY_P2P

// odeslani prop B zpravy
#ifdef J1939_PROPRIETARY_BCAST
bool_t J1939SendPropBCastMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t Priority,
		const uint8_t DataPage, const uint8_t GE, const void * const Data, const J1939_MSGSIZE Size);
#endif // J1939_PROPRIETARY_BCAST


#ifdef J1939_REQUEST

bool_t J1939SendRequestMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t DestAddr,
		const uint32_t PGN);

bool_t J1939SendAckMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t DestAddr,
		const J1939_ACKTYPE ackType, const uint8_t GrpFuncVal, const uint32_t PGN);

#endif // J1939_REQUEST

//----------------------------------------------------
/**
	\brief	Odeslani obecne zpravy
*/
//----------------------------------------------------

bool_t J1939SendGenericMsg(J1939_CTX * const jctx, J1939_BUFFER * const Buf, const uint8_t Priority,
		const uint8_t DataPage, const uint8_t PF, const uint8_t PS, const uint8_t * const Data, const uint8_t Size);

//----------------------------------------------------
/**
	\brief	Pozastaveni prijmu threadu
	\return	True, je-li pozastavitelny
*/
//----------------------------------------------------
bool_t J1939PauseThread(J1939_RECV_THREAD_CTX * const tctx);

//----------------------------------------------------
/**
	\brief	Obnoveni cinnosti threadu
*/
//----------------------------------------------------
bool_t J1939ResumeThread(J1939_RECV_THREAD_CTX * const tctx);

//----------------------------------------------------
/**
	\brief	Nastavi prodlevy mezi jednotlivymi zpravami
*/
//----------------------------------------------------
void J1939SetSendDelays(J1939_CTX * const jctx, const ticks_t P2PDelay, const ticks_t BCastDelay);

bool_t J1939Initialize(
		J1939_CTX * const jctx,
		CANCOMMDESC * const cmm,
#ifdef J1939_ADDRESSCLAIM
		const uint64_t Name,
#else
		const uint8_t		Address,
#endif // J1939_ADDRESSCLAIM
		const uint8_t Priority);


void J1939Finalize(J1939_CTX * const ctx);

#endif /*J1939_H_*/
