//=====================================================================
//文件名称：SPI.h
//功能概要：SPI头文件
//版权所有：苏州大学飞思卡尔嵌入式中心(sumcu.suda.edu.cn)
//更新记录：2016-03-17 
//=====================================================================
#ifndef _SPI_H             //防止重复定义（ 开头)
#define _SPI_H

#include "common.h"      //包含公共要素头文件
//宏定义：定义SPI口号。
#define SPI_0  0     //SPI0口
#define SPI_1  1     //SPI1口

//根据SPI实际硬件引脚，确定以下宏常量值。
//在此工程中，我们只使用SPI0组中的第2个，SPI1组中的第2个，
//因此我们在此只需要将SPI_0_GROUP宏定义为2,SPI_1_GROUP宏定义为2。

//SPI_0：1=PTD0、1、2、3脚，2=PTA14、15、16、17脚，3=PTC4、5、6、7脚
#define SPI_0_GROUP  3   //SD-FSL-KL25-EVB板上使用PTA14~17脚

//SPI_1：1=PTE1、2、3、4脚，2=PTB10、11、16、17脚，3=PTD4、5、6、7脚
#define SPI_1_GROUP  3    //SD-FSL-KL25-EVB板上使用PTB10、11、16、17脚

#define SPI_baseadd(SPI_nub) (SPI_MemMapPtr)(0x40076000u+SPI_nub*0x00001000u)

//KW01暂时添加宏定义
//#include "includes.h"
/************************************************************************************
* MCU SPI module configuration constants
************************************************************************************/
// SPI Control Register 1
//                            .--------- SPIE     : SPI Interrupt (SPRF and MODF) disabled
//                            |.-------- SPE      : SPI System inactive
//                            ||.------- SPTIE    : SPI Transmit Interrupt disabled
//                            |||.------ MSTR     : Master/Slave Mode Select.
//                            ||||.----- CPOL     : Clock Polarity. Active High
//                            |||||.---- CPHA     : Clock Phase. First edge on SPSCK occurs at the middle of the first cycle of an 8-cycle data transfer
//                            ||||||.--- SSOE     : Slave Select Output Enable
//                            |||||||.-- LSBFE    : LSB First (Shifter Direction). SPI serial data transfers start with most significant bit
//                            ||||||||
#define CSPIC1_INIT  0x00 //0b00010000
// SPI Control Register 2
//                            .--------- SPMIE       : SPI match interrupt enable
//                            |.-------- SPIMODE     : SPI 8-bit or 16-bit mode
//                            ||.------- TXDMAE      : Transmit DMA Enable
//                            |||.------ MODFEN      : Master Mode-Fault Function disabled.
//                            ||||.----- BIDIROE     : Bidirectional Mode Output Enable disabled
//                            |||||.---- RXDMAE      : Receive DMA enable
//                            ||||||.--- SPISWAI     : SPI Stop in Wait Mode. SPI clocks continue to operate in wait mode
//                            |||||||.-- SPC0        : SPI Pin Control 0. SPI uses separate pins for data input and data output.
//                            ||||||||
#define CSPIC2_INIT  0x00 //0b00000000
// SPI Baud Rate Register. Master SPI CLOCK = BUS CLOCK / Prescaler Divisor / SPI Rate Divisor = BUS CLOCK / 2
//                            .--------- X        : Unimplemented or Reserved
//                            |...------ SPPR[2:0]: SPI Baud Rate Prescale Divisor. Prescaler Divisor = 1
//                            ||||....-- SPR[3:0] : SPI Baud Rate Divisor. SPI Rate Divisor = 2
//                            ||||||||
#define CSPIBR_INIT   0x00   //0b001110010    /                                 /Original line, SPICLK=BUS_CLK/2 (2: baud rate divisor)
//#define cSPIBR_Init   0x01                                                    //modif->  SPICLK=BUS_CLK/4 (4: baud rate divisor)
//#define cSPIBR_Init   0x02                                                    //modif->  SPICLK=BUS_CLK/8 (8: baud rate divisor)
//#define cSPIBR_Init   0x04                                                    //modif->  SPICLK=BUS_CLK/32 (32: baud rate divisor)
//#define cSPIBR_Init   0x08                                                    //modif->  SPICLK=BUS_CLK/512 (512: baud rate divisor)

/* SPI Status Register masks */


//RF模块相关（SPI通信设置）
#define MKW01DRV_DEASSERTRESET()    { GPIOE_PCOR |= (1<<30); }      //写1清对应的PTE30的数据输出寄存器，使PDOR为0
#define MKW01DRV_ASSERTRESET()      { GPIOE_PDOR |= (1<<30);}       //输出设置为逻辑1

#define SPID_DUMMYREAD              {SPI0_BASE_PTR->DL;}//{char dummy = SPI0_BASE_PTR->D;}
#define SPIS_DUMMYREAD              {SPI0_BASE_PTR->S;}

//#define AssertSS                    {GPIOC_PCOR |= (uint_8)(1<<4);}//写1清对应的PTC4的数据输出寄存器，使PDOR为0（打开主从通信）
//#define DeAssertSS                  {GPIOC_PDOR |= (uint_8)(1<<4);}//输出设置为逻辑1(关闭主从通信)

#define ASSERTSS                    {GPIOD_PCOR |= (uint_8)(1<<0);}//写1清对应的PTD0的数据输出寄存器，使PDOR为0（打开主从通信）
#define DEASSERTSS                  {GPIOD_PDOR |= (uint_8)(1<<0);}//输出设置为逻辑1(关闭主从通信)

#define WAIT_SPITX_BUFFER_EMPTY     {while(!(SPI0_BASE_PTR->S & SPI_S_SPTEF_MASK));}
#define WAIT_SPIRX_BUFFER_FULL      {while(!(SPI0_BASE_PTR->S & SPI_S_SPRF_MASK));}
#define WAIT_SPI_TRANSMITTER_EMPTY  {WAIT_SPITX_BUFFER_EMPTY; Wait_6_BitClks();  }

#define MKW01Drv_WriteRegisterFastMacro(addr, val)\
  SPIS_DUMMYREAD;\
  ASSERTSS;\
  SPI0_BASE_PTR->DL = (unsigned char)(addr | 0x80);\
  WAIT_SPITX_BUFFER_EMPTY;\
  SPID_DUMMYREAD;\
  SPI0_BASE_PTR->DL = (unsigned char)(val);\
  WAIT_SPITX_BUFFER_EMPTY;\
  SPID_DUMMYREAD;\
  WAIT_SPIRX_BUFFER_FULL;\
  DEASSERTSS;\


#define MKW01Drv_ReadRegisterFastMacro(addr, val)\
  SPIS_DUMMYREAD;\
  ASSERTSS;\
  SPI0_BASE_PTR->DL = (unsigned char)(addr);\
  WAIT_SPITX_BUFFER_EMPTY;\
  SPID_DUMMYREAD;\
  SPI0_BASE_PTR->DL = 0x00;\
  WAIT_SPITX_BUFFER_EMPTY;\
  SPID_DUMMYREAD;\
  WAIT_SPIRX_BUFFER_FULL;\
  (val) = SPI0_BASE_PTR->DL;\
  DEASSERTSS;\
//KW01暂时添加宏定义区结束

//=======================函数注释区=======================================
//=====================================================================
//函数名称：spi_init。
//功能说明：SPI初始化
//函数参数：No：模块号，KL25芯片取值为0、1
//       MSTR：SPI主从机选择，0选择为主机,1选择为从机。
//       BaudRate：波特率，可取12000、6000、4000、3000、1500、1000，单位：b/s
//       CPOL：CPOL=0：高有效SPI时钟（低无效）；CPOL=1：低有效SPI时钟（高无效）
//       CPHA：CPHA=0相位为0； CPHA=1相位为1；
//函数返回：无
//函数备注： CPHA=0，时钟信号的第一个边沿出现在8周期数据传输的第一个周期的中央；
//        CPHA=1，时钟信号的第一个边沿出现在8周期数据传输的第一个周期的起点。
//        CPHA=0时，通信最稳定，即接收方在1/2周期的时刻从线上取数。
//=====================================================================
//void spi_init(uint_8 No,uint_8 MSTR,uint_16 BaudRate,uint_8 CPOL,\
//                                                         uint_8 CPHA);

//=====================================================================
//函数名称：spi_send1.
//功能说明：SPI发送一字节数据。
//函数参数：No：模块号。 其取值为0或1
//       data：     需要发送的一字节数据。
//函数返回：0：发送失败；1：发送成功。
//=====================================================================
//uint_8 spi_send1(uint_8 No,uint_8 data);

//=====================================================================
//函数名称：spi_sendN.
//功能说明：SPI发送数据。
//函数参数：No：模块号。 其取值为0或1
//       n:     要发送的字节个数。范围为(1~255)
//       data[]:所发数组的首地址。
//函数返回：无。
//=====================================================================
//void spi_sendN(uint_8 No,uint_8 n,uint_8 data[]);

//=====================================================================
//函数名称：spi_receive1.
//功能说明：SPI接收一个字节的数据
//函数参数：No：模块号。 其取值为0或1
//函数返回：接收到的数据。
//=====================================================================
//uint_8 spi_receive1(uint_8 No);

//=====================================================================
//函数名称：spi_receiveN.
//功能说明：SPI接收数据。当n=1时，就是接受一个字节的数据……
//函数参数：No：模块号。 其取值为0或1
//          n:    要发送的字节个数。范围为(1~255),
//       data[]:接收到的数据存放的首地址。
//函数返回：1：接收成功,其他情况：失败。
//=====================================================================
//uint_8 spi_receiveN(uint_8 No,uint_8 n,uint_8 data[]);

//=====================================================================
//函数名称：spi_enable_re_int
//功能说明：打开SPI接收中断。
//函数参数：No：模块号。 其取值为0或1。
//函数返回：无。
//=====================================================================
//void spi_enable_re_int(uint_8 No);

//=====================================================================
//函数名称：spi_disable_re_int
//功能说明：关闭SPI接收中断。
//函数参数：No：模块号。 其取值为0或1。
//函数返回：无。
//=====================================================================
//void spi_disable_re_int(uint_8 No);
//=======================函数注释区结束====================================

//=======================函数定义区=======================================
#define MKW01Drv_SPI0_Init ((void (*)())(bios_fun_point[55]))

#define spi_init  ((void (*)(uint_8 No,uint_8 MSTR,uint_16 BaudRate,uint_8 CPOL,uint_8 CPHA))(bios_fun_point[56]))

#define spi_send1  ((uint_8 (*)(uint_8 No,uint_8 data))(bios_fun_point[57]))

#define spi_sendN  ((void (*)(uint_8 No,uint_8 n,uint_8 data[]))(bios_fun_point[58]))

#define spi_receive1  ((uint_8 (*)(uint_8 No))(bios_fun_point[59]))

#define spi_receiveN  ((uint_8 (*)(uint_8 No,uint_8 n,uint_8 data[]))(bios_fun_point[60]))

#define spi_enable_re_int  ((void (*)(uint_8 No))(bios_fun_point[61]))

#define spi_disable_re_int  ((void (*)(uint_8 No))(bios_fun_point[62]))

#define MKW01Drv_ReadRegister ((uint_8 (*)(uint_8 addr))(bios_fun_point[63]))

#define MKW01Drv_WriteRegister ((void (*)(uint_8 addr, uint_8 val))(bios_fun_point[64]))

#define MKW01Drv_WriteRegisterFast ((void (*)(uint_8 addr, uint_8 val))(bios_fun_point[65]))
//=======================函数定义区结束=====================================
#endif   //防止重复定义（ 结尾)

//=====================================================================
//声明：
//（1）我们开发的源代码，在本中心提供的硬件系统测试通过，真诚奉献给社会，不足之处，
//     欢迎指正。
//（2）对于使用非本中心硬件系统的用户，移植代码时，请仔细根据自己的硬件匹配。
//
//苏州大学NXP嵌入式中心(http://sumcu.suda.edu.cn,0512-65214835)
