/* 
* classCan.h
*
* Created: 23/05/2018 17:40:58
* Author: Ledo
*/


#ifndef __CLASSCAN_H__
#define __CLASSCAN_H__

#include <sam4e.h>

/** Define the Mailbox mask for eight mailboxes. */
#define GLOBAL_MAILBOX_MASK           0x000000ff

/** Disable all interrupt mask */
#define CAN_DISABLE_ALL_INTERRUPT_MASK 0xffffffff

/** Define the typical baudrate for CAN communication in KHz. */
#define CAN_BPS_1000K                 1000
#define CAN_BPS_800K                  800
#define CAN_BPS_500K                  500
#define CAN_BPS_250K                  250
#define CAN_BPS_125K                  125
#define CAN_BPS_50K                   50
#define CAN_BPS_25K                   25
#define CAN_BPS_10K                   10
#define CAN_BPS_5K                    5

/** Define the mailbox mode. */
#define CAN_MB_DISABLE_MODE           0
#define CAN_MB_RX_MODE                1
#define CAN_MB_RX_OVER_WR_MODE        2
#define CAN_MB_TX_MODE                3
#define CAN_MB_CONSUMER_MODE          4
#define CAN_MB_PRODUCER_MODE          5

/** Define CAN mailbox transfer status code. */
#define CAN_MAILBOX_TRANSFER_OK       0     /**< Read from or write into mailbox
	                                           successfully. */
#define CAN_MAILBOX_NOT_READY         0x01  /**< Receiver is empty or
	                                           transmitter is busy. */
#define CAN_MAILBOX_RX_OVER           0x02  /**< Message overwriting happens or
	                                           there're messages lost in
	                                           different receive modes. */
#define CAN_MAILBOX_RX_NEED_RD_AGAIN  0x04  /**< Application needs to re-read
	                                           the data register in Receive with
/** Define the timemark mask. */
#define TIMEMARK_MASK              0x0000ffff

/* CAN timeout for synchronization. */
#define CAN_TIMEOUT                100000

/** The max value for CAN baudrate prescale. */
#define CAN_BAUDRATE_MAX_DIV       128

/** Define the scope for TQ. */
#define CAN_MIN_TQ_NUM             8
#define CAN_MAX_TQ_NUM             25

/** Define the fixed bit time value. */
#define CAN_BIT_SYNC               1
#define CAN_BIT_IPT                2	            

/** Define the struct for CAN message mailbox. */
typedef struct {
	uint32_t ul_mb_idx;
	uint8_t uc_obj_type;  /**< Mailbox object type, one of the six different
	                         objects. */
	uint8_t uc_id_ver;    /**< 0 stands for standard frame, 1 stands for
	                         extended frame. */
	uint8_t uc_length;    /**< Received data length or transmitted data
	                         length. */
	uint8_t uc_tx_prio;   /**< Mailbox priority, no effect in receive mode. */
	uint32_t ul_status;   /**< Mailbox status register value. */
	uint32_t ul_id_msk;   /**< No effect in transmit mode. */
	uint32_t ul_id;       /**< Received frame ID or the frame ID to be
	                         transmitted. */
	uint32_t ul_fid;      /**< Family ID. */
	uint32_t ul_datal;
	uint32_t ul_datah;
} can_mb_conf_t;

typedef struct {
	uint8_t uc_tq;      /**< CAN_BIT_SYNC + uc_prog + uc_phase1 + uc_phase2
	                       = uc_tq, 8 <= uc_tq <= 25. */
	uint8_t uc_prog;    /**< Propagation segment, (3-bits + 1), 1~8; */
	uint8_t uc_phase1;  /**< Phase segment 1, (3-bits + 1), 1~8; */
	uint8_t uc_phase2;  /**< Phase segment 2, (3-bits + 1), 1~8, CAN_BIT_IPT
	                       <= uc_phase2; */
	uint8_t uc_sjw;     /**< Resynchronization jump width, (2-bits + 1),
	                       min(uc_phase1, 4); */
	uint8_t uc_sp;      /**< Sample point value, 0~100 in percent. */
} can_bit_timing_t;

/** Values of bit time register for different baudrates, Sample point =
 * ((1 + uc_prog + uc_phase1) / uc_tq) * 100%. */
const can_bit_timing_t can_bit_time[] = {
	{ 8, (2 + 1), (1 + 1), (1 + 1), (2 + 1), 75},
	{ 9, (1 + 1), (2 + 1), (2 + 1), (1 + 1), 67},
	{10, (2 + 1), (2 + 1), (2 + 1), (2 + 1), 70},
	{11, (3 + 1), (2 + 1), (2 + 1), (3 + 1), 72},
	{12, (2 + 1), (3 + 1), (3 + 1), (3 + 1), 67},
	{13, (3 + 1), (3 + 1), (3 + 1), (3 + 1), 77},
	{14, (3 + 1), (3 + 1), (4 + 1), (3 + 1), 64},
	{15, (3 + 1), (4 + 1), (4 + 1), (3 + 1), 67},
	{16, (4 + 1), (4 + 1), (4 + 1), (3 + 1), 69},
	{17, (5 + 1), (4 + 1), (4 + 1), (3 + 1), 71},
	{18, (4 + 1), (5 + 1), (5 + 1), (3 + 1), 67},
	{19, (5 + 1), (5 + 1), (5 + 1), (3 + 1), 68},
	{20, (6 + 1), (5 + 1), (5 + 1), (3 + 1), 70},
	{21, (7 + 1), (5 + 1), (5 + 1), (3 + 1), 71},
	{22, (6 + 1), (6 + 1), (6 + 1), (3 + 1), 68},
	{23, (7 + 1), (7 + 1), (6 + 1), (3 + 1), 70},
	{24, (6 + 1), (7 + 1), (7 + 1), (3 + 1), 67},
	{25, (7 + 1), (7 + 1), (7 + 1), (3 + 1), 68}
};



class classCan
{
//variables
public:
protected:
private:

//functions
public:
	classCan();
	~classCan();
	uint32_t can_set_baudrate(Can *p_can, uint32_t ul_mck,
	uint32_t ul_baudrate);
	uint32_t can_init(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate);
	void can_enable(Can *p_can);
	void can_disable(Can *p_can);
	void can_disable_low_power_mode(Can *p_can);
	void can_enable_low_power_mode(Can *p_can);
	void can_disable_autobaud_listen_mode(Can *p_can);
	void can_enable_autobaud_listen_mode(Can *p_can);
	void can_disable_overload_frame(Can *p_can);
	void can_enable_overload_frame(Can *p_can);
	void can_set_timestamp_capture_point(Can *p_can, uint32_t ul_flag);
	void can_disable_time_triggered_mode(Can *p_can);
	void can_enable_time_triggered_mode(Can *p_can);
	void can_disable_timer_freeze(Can *p_can);
	void can_enable_timer_freeze(Can *p_can);
	void can_disable_tx_repeat(Can *p_can);
	void can_enable_tx_repeat(Can *p_can);
	void can_enable_interrupt(Can *p_can, uint32_t dw_mask);
	void can_disable_interrupt(Can *p_can, uint32_t dw_mask);
	uint32_t can_get_interrupt_mask(Can *p_can);
	uint32_t can_get_status(Can *p_can);
	uint32_t can_get_internal_timer_value(Can *p_can);
	uint32_t can_get_timestamp_value(Can *p_can);
	uint8_t can_get_tx_error_cnt(Can *p_can);
	uint8_t can_get_rx_error_cnt(Can *p_can);
	void can_reset_internal_timer(Can *p_can);
	void can_global_send_transfer_cmd(Can *p_can, uint8_t uc_mask);
	void can_global_send_abort_cmd(Can *p_can, uint8_t uc_mask);
	void can_mailbox_set_timemark(Can *p_can, uint8_t uc_index, uint16_t us_cnt);
	uint32_t can_mailbox_get_status(Can *p_can, uint8_t uc_index);
	void can_mailbox_send_transfer_cmd(Can *p_can, can_mb_conf_t *p_mailbox);
	void can_mailbox_send_abort_cmd(Can *p_can, can_mb_conf_t *p_mailbox);
	void can_mailbox_init(Can *p_can, can_mb_conf_t *p_mailbox);
	uint32_t can_mailbox_read(Can *p_can, can_mb_conf_t *p_mailbox);
	uint32_t can_mailbox_write(Can *p_can, can_mb_conf_t *p_mailbox);
	uint32_t can_mailbox_tx_remote_frame(Can *p_can, can_mb_conf_t *p_mailbox);
	void can_reset_all_mailbox(Can *p_can);
	void reset_mailbox_conf(can_mb_conf_t *p_mailbox);


protected:
private:
	classCan( const classCan &c );
	classCan& operator=( const classCan &c );

}; //classCan

#endif //__CLASSCAN_H__
