/*
 * SPItoFPGAOperation.c
 *
 * Copyright (C) 2024 MACNICA,Inc. All Rights Reserved.
 *  This software is licensed "AS IS".
 *  Please perform use of this software by a user's own responsibility and expense.
 *  It cannot guarantee in the maker side about the damage which occurred
 *  by the ab-ility not to use or use this software, and all damage that occurred secondarily.
 *  Created on: 2024/02/26
 *      Author: 12088
 */

#ifndef _SPI_TO_FPGA_OPERATION_H_
#define _SPI_TO_FPGA_OPERATION_H_

#include "fsl_spi.h"
#include "transaction_to_packet.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define EXAMPLE_SPI_MASTER          SPI2
#define EXAMPLE_SPI_MASTER_IRQ      FLEXCOMM2_IRQn
#define EXAMPLE_SPI_MASTER_CLK_SRC  kCLOCK_Flexcomm2
#define EXAMPLE_SPI_MASTER_CLK_FREQ CLOCK_GetFlexCommClkFreq(2)
#define EXAMPLE_SPI_SSEL            0
#define EXAMPLE_SPI_SPOL            kSPI_SpolActiveAllLow
#define SPI_BASE					(unsigned long)EXAMPLE_SPI_MASTER

// ------------------------------------
// Transaction size
// ------------------------------------
#define BUFFER_LENGTH		1024

// -----------------------------------------------------------------------
// INCREMENT ADDRESS - starting from the given address, data will be
//						read/write to incrementing address
// NON_INCREMEMT_ADDRESS - data will read/write only to the given address
//(If data size is more than 4 bytes, the 1st four data will be overwrite
//	by the next 4 bytes , due to non-increment address
// -----------------------------------------------------------------------
#define INCREMENT_ADDRESS			1
#define NON_INCREMENT_ADDRESS		0

// -----------------------------------------------------------------------
//  Address Map for SPI-to-AVMM.Avalon-Master
// -----------------------------------------------------------------------
// fifo_txevent_01.out		0x00000000 - 0x00000003
// fifo_txevent_01.out_csr	0x00000020 - 0x0000003f
// fifo_txdata_0.out		0x00000040 - 0x00000043
// fifo_txdata_0.out_csr	0x00000060 - 0x0000007f
// fifo_txdata_1.out		0x00000080 - 0x00000083
// fifo_txdata_1.out_csr	0x000000a0 - 0x000000bf
// fifo_rxbuff_0.in			0x00000140 - 0x00000143
// fifo_rxbuff_0.in_csr		0x00000160 - 0x0000017f
// fifo_rxbuff_1.in			0x00000180 - 0x00000183
// fifo_rxbuff_1.in_csr		0x000001a0 - 0x000001bf
// mm_bridge_1.so (ocram)	0x00020000 - 0x0003ffff
#define FIFO_TXEVENT01_BASE		0x00000000
#define FIFO_TXEVENT01_CSR_BASE	0x00000020
#define FIFO_TXDATA0_BASE		0x00000040
#define FIFO_TXDATA0_CSR_BASE	0x00000060
#define FIFO_TXDATA1_BASE		0x00000080
#define FIFO_TXDATA1_CSR_BASE	0x000000a0
#define FIFO_RXBUFF0_BASE		0x00000140
#define FIFO_RXBUFF0_CSR_BASE	0x00000160
#define FIFO_RXBUFF1_BASE		0x00000180
#define FIFO_RXBUFF1_CSR_BASE	0x000001a0
#define FPGA_OCRAM_BASE			0x00020000

#define FIFO_LEVEL_REG          0x00
#define FIFO_STATUS_REG         0x04
#define FIFO_EVENT_REG          0x08
#define FIFO_IENABLE_REG        0x0C
#define FIFO_ALMOSTFULL_REG     0x10
#define FIFO_ALMOSTEMPTY_REG    0x14

#define FIFO_STATUS_F_MSK       0x01
#define FIFO_STATUS_E_MSK       0x02
#define FIFO_STATUS_AF_MSK      0x04
#define FIFO_STATUS_AE_MSK      0x08
#define FIFO_STATUS_OVF_MSK     0x10
#define FIFO_STATUS_UDF_MSK     0x20
#define FIFO_STATUS_ALL         0x3F

#if 0
/*! @brief MCAN Tx Buffer FPGA Event FIFO structure. */
typedef union _mcan_fpga_tx_event_fifo_1st
{
	uint32_t	word;		/*!< #1 先頭データ (Word アクセス用) */
	struct
	{
		uint32_t	id : 29;		/*!< Base ID(11bit) + ID Extension(18bit) (29bit) */
		
		uint32_t	evt_or_buf : 1;	/*!< Event(1) or Buffer(0) (1bit) */
		uint32_t	can0_or_1 : 1;	/*!< CAN0(0) or CAN1(1) (1bit) */
		uint32_t	top : 1;		/*!< 先頭データ(1) (1bit) */
	} field;
} mcan_fpga_tx_event_fifo_1st_t;

typedef union _mcan_fpga_tx_event_fifo_2nd
{
	uint32_t	word;		/*!< #2 ２番目データ (Word アクセス用) */
	struct
	{
		uint32_t	txts : 16;		/*!< 送信タイムスタンプ (16bit) */
		uint32_t	dlc : 4;		/*!< Data Length Code (4bit) */
		uint32_t	brs : 1;		/*!< Bit Rate Switch. レート変更有り(1) (1bit) */
		uint32_t	fdf : 1;		/*!< CAN FD format. CAN(0) or CANFD(1) (1bit) */
		uint32_t	et : 2;			/*!< ET. Event: ET[1:0] / Buffer:FEC(1bit),Reserved(1bit) */
		uint32_t : 1;				/*!< Reserved. */
		uint32_t	rtr : 1;		/*!< RTR データ(0) or リモート(1) (1bit) */
		uint32_t	ide : 1;		/*!< IDE 標準(0) or 拡張(1) (1bit) */
		uint32_t	esi : 1;		/*!< ESI エラー通知(1) (1bit) */
		uint32_t : 1;				/*!< Reserved. */
		
		uint32_t	evt_or_buf : 1;	/*!< Event(1) or Buffer(0) (1bit) */
		uint32_t	can0_or_1 : 1;	/*!< CAN0(0) or CAN1(1) (1bit) */
		uint32_t	top : 1;		/*!< 先頭以外のデータ(0) (1bit) */
	} field;
} mcan_fpga_tx_event_fifo_2nd_t;

/*! @brief MCAN Rx FIFO/Buffer structure. */
typedef union _mcan_fpga_rx_fifo_1st
{
	uint32_t	word;		/*!< #1 先頭データ (Word アクセス用) */
	struct
	{
		uint32_t id : 29; /*!< CAN Frame Identifier. */
		uint32_t rtr : 1; /*!< CAN Frame Type(DATA or REMOTE). */
		uint32_t xtd : 1; /*!< CAN Frame Type(STD or EXT). */
		uint32_t esi : 1; /*!< CAN Frame Error State Indicator. */
	};
} mcan_fpga_rx_fifo_1st_t;

typedef union _mcan_fpga_rx_fifo_2nd
{
	uint32_t	word;		/*!< #1 ２番目データ (Word アクセス用) */
	struct
	{
		uint32_t rxts : 16; /*!< Rx Timestamp. */
		uint32_t dlc : 4;   /*!< Data Length Code      9 10 11 12 13 14 15
		                         Number of data bytes 12 16 20 24 32 48 64 */
		uint32_t brs : 1;   /*!< Bit Rate Switch. */
		uint32_t fdf : 1;   /*!< CAN FD format. */
		uint32_t : 2;       /*!< Reserved. */
		uint32_t fidx : 7;  /*!< Filter Index. */
		uint32_t anmf : 1;  /*!< Accepted Non-matching Frame. */
	};
} mcan_fpga_rx_fifo_2nd_t;
#endif

/*******************************************************************************
 * Prototypes
 ******************************************************************************/
void SPIM_INIT(void);

int spi_command(unsigned int base, unsigned int slave, unsigned int write_length, const unsigned char * write_data,
                 unsigned int read_length, unsigned char * read_data, unsigned int flags);
#if 0
inline int spi_command(unsigned int base, unsigned int slave, unsigned int write_length, const unsigned char * write_data,
                 unsigned int read_length, unsigned char * read_data, unsigned int flags)
{
    spi_transfer_t xfer = {0};

	//----------------------------------------------------------------------------------------
    // alt_avalon_spi_command() is Altera's SPI Driver function. If you are using another SPI
	// driver, replace this with your own SPI Driver functions.
    //----------------------------------------------------------------------------------------
	//alt_avalon_spi_command(base,slave,write_length,write_data,read_length,read_data,flags);
    /*Start Transfer*/
    xfer.txData      = (uint8_t*)write_data;
    xfer.rxData      = (uint8_t*)read_data;
    xfer.dataSize    = write_length + read_length;
    xfer.configFlags = kSPI_FrameAssert;
    SPI_MasterTransferBlocking((SPI_Type*)base, &xfer);

	return 0;
}
#endif

status_t fpga_spi_bridge_write(uint32_t target_addr, uint8_t *data, size_t txSize);
status_t fpga_spi_bridge_sequential_write(uint32_t target_addr, uint8_t *data, size_t txSize);
status_t fpga_spi_bridge_read(uint32_t target_addr, uint8_t *data, size_t rxSize);
status_t fpga_spi_bridge_sequential_read(uint32_t target_addr, uint8_t *data, size_t rxSize);

/*******************************************************************************
 * Variables
 ******************************************************************************/

#endif /* _SPI_TO_FPGA_OPERATION_H_ */
