/******************************************************************************
�� �� ����SPI_Master.c
����������SPI ����ģʽ�������ļ�
��    �ߣ�����
��    ����V1.0
��    �ڣ�2017.04.02
******************************************************************************/

#include "SPI_Master.h"

SPIDataBlockStruct      SPIDataBlock;

/******************************************************************************
��������SPI_Master_Start
��  �ܣ���ʼ��������SPI����ģʽ
��  ����Mode��SPI����ģʽ��         SPI_MODE_0
                                    SPI_MODE_1
                                    SPI_MODE_2
                                    SPI_MODE_3

        FirstBit�����ȷ��͵�����λ��SPI_MSB_FIRST
                                    SPI_LSB_FIRST
����ֵ����
******************************************************************************/
void SPI_Master_Start(uint8_t Mode, uint8_t FirstBit)
{
  SPICR1  = 0x00;

  PTSRR  &= 0xCF;
  PTSRR  |= SPI_GPIO_SELECT;

  SPIBR   = 0x32;                 //Baud Rate = BUSCLK / ((3 + 1) * 2 ^ (2 + 1)) = 1000000

  SPICR2 &= 0x40;

  SPICR1  = 0x50 | Mode | FirstBit;
}

/******************************************************************************
��������SPI_Master_Stop
��  �ܣ��ر�SPI����
��  ������
����ֵ����
******************************************************************************/
void SPI_Master_Stop(void)
{
  SPICR1 &= 0x1D;                 //�ر�SPI
}

/******************************************************************************
��������SPI_Master_Get_Write_Status
��  �ܣ���ȡ��ǰд��״̬
��  ������
����ֵ��SPI_WRITE_COMPLETE    ������д�����
        SPI_WRITE_NOT_COMPLETE������д��δ���
******************************************************************************/
uint8_t SPI_Master_Get_Write_Status(void)
{
  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_WRITE_NOT_COMPLETE;

  if (SPISR_SPIF)
    return SPI_WRITE_COMPLETE;

  return SPI_WRITE_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Byte_Write
��  �ܣ���SPI������дһ�ֽ�
��  ����Data:Ҫд�������
����ֵ��SPI_WRITE_COMPLETE�����ݳɹ�д��
        SPI_UNWRITABLE    ����ǰ����д��
******************************************************************************/
uint8_t SPI_Master_Byte_Write(uint8_t Data)
{
  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_UNWRITABLE;

  if (SPISR_SPTEF)                //���ݼĴ���Ϊ��ʱ����д��
  {
    SPICR2 &= 0xBF;               //����8���
    SPIDRL = Data;
    return SPI_WRITE_COMPLETE;
  }

  return SPI_UNWRITABLE;
}

/******************************************************************************
��������SPI_Master_Byte_Read_Req
��  �ܣ�������SPI�����϶�ȡһ�ֽ�����
��  ������
����ֵ��SPI_READ_REQ_COMPLETE����ȡ����ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Byte_Read_Req(void)
{
  uint8_t Data;

  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPIF)
    Data = SPIDRL;                //���ռĴ�����Ϊ������ս��ռĴ���

  if (SPISR_SPTEF)                //���ݼĴ���Ϊ��ʱ����д��
  {
    SPICR2 &= 0xBF;               //����8���
    SPIDRL = SPI_DUMMY_BYTE;
    return SPI_READ_REQ_COMPLETE;
  }

  return SPI_READ_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Get_Read_Byte
��  �ܣ���ȡ��SPI�����϶�����һ�ֽ�����
��  ����pData�����ڴ洢�������ݵı���
����ֵ��SPI_READ_COMPLETE    ����ȡ�ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Get_Read_Byte(uint8_t *pData)
{
  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPIF)
  {
    *pData = SPIDRL;
    return SPI_READ_COMPLETE;
  }

  return SPI_READ_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Word_Write
��  �ܣ���SPI������дһ����(16bit)
��  ����Data:Ҫд�������
����ֵ��SPI_WRITE_COMPLETE�����ݳɹ�д��
        SPI_UNWRITABLE    ����ǰ����д��
******************************************************************************/
uint8_t SPI_Master_Word_Write(uint16_t Data)
{
  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_UNWRITABLE;

  if (SPISR_SPTEF)                //���ݼĴ���Ϊ��ʱ����д��
  {
    SPICR2 |= 0x40;               //����16���
    SPIDR = Data;
    return SPI_WRITE_COMPLETE;
  }

  return SPI_UNWRITABLE;
}

/******************************************************************************
��������SPI_Master_Word_Read_Req
��  �ܣ�������SPI�����϶�ȡһ����(16bit)������
��  ������
����ֵ��SPI_READ_REQ_COMPLETE����ȡ����ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Word_Read_Req(void)
{
  uint16_t Data;

  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPIF)
    Data = SPIDR;                 //���ռĴ�����Ϊ������ս��ռĴ���

  if (SPISR_SPTEF)                //���ݼĴ���Ϊ��ʱ����д��
  {
    SPICR2 |= 0x40;               //����16���
    SPIDR = SPI_DUMMY_WORD;
    return SPI_READ_REQ_COMPLETE;
  }

  return SPI_READ_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Get_Read_Word
��  �ܣ���ȡ��SPI�����϶�����һ����(16bit)������
��  ����pData�����ڴ洢�������ݵı���
����ֵ��SPI_READ_COMPLETE    ����ȡ�ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Get_Read_Word(uint16_t *pData)
{
  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPIF)
  {
    *pData = SPIDR;
    return SPI_READ_COMPLETE;
  }

  return SPI_READ_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Block_Write
��  �ܣ���SPI������дһ�����ݿ�
��  ����pData��Ҫд������ݿ�
        Len  �����ݿ鳤��
����ֵ��SPI_WRITE_COMPLETE�����ݳɹ�д��
        SPI_UNWRITABLE    ����ǰ����д��
******************************************************************************/
uint8_t SPI_Master_Block_Write(uint8_t *pData, uint8_t Len)
{
  uint8_t i;

  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_UNWRITABLE;        //����ж�д���ڽ�������ֹд��

  if ((Len == 0) || (Len > SPI_DATA_BUFFER_SIZE))
    return SPI_UNWRITABLE;

  SPIDataBlock.Ptr = 0;
  SPIDataBlock.ReadComplete = 0;  //���ݱ�����,�����־
  SPIDataBlock.Len = Len;
  for (i = 0; i < Len; i++)
    SPIDataBlock.Data[i] = pData[i];

  if (SPISR_SPTEF == 0)           //�洢���ǿ�״̬����д��
    return SPI_UNWRITABLE;

  SPIDataBlock.Status = SPI_DATA_BLOCK_WRITE;

  SPICR1 |= 0x20;                 //���������ж�
  SPICR2 &= 0xBF;                 //����8���
  SPIDRL = SPIDataBlock.Data[SPIDataBlock.Ptr];

  return SPI_WRITE_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Block_Read_Req
��  �ܣ�������SPI�����϶�ȡһ�����ݿ�
��  ����Len�����ݿ�ij���
����ֵ��SPI_READ_REQ_COMPLETE����ȡ����ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Block_Read_Req(uint8_t Len)
{
  uint8_t Data;

  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE; //����ж�д���ڽ�������ֹ��ȡ

  if ((Len == 0) || (Len > SPI_DATA_BUFFER_SIZE))
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPTEF == 0)           //�洢���ǿ�״̬����д��
    return SPI_READ_NOT_COMPLETE;

  if (SPISR_SPIF)
    Data = SPIDRL;                //���ռĴ�����Ϊ������ս��ռĴ���

  SPIDataBlock.Status = SPI_DATA_BLOCK_READ;
  SPIDataBlock.Ptr = 0;
  SPIDataBlock.ReadComplete = 0;
  SPIDataBlock.Len = Len;

  SPICR1 |= 0x80;                 //���������ж�
  SPICR2 &= 0xBF;                 //����8���
  SPIDRL = SPI_DUMMY_BYTE;

  return SPI_READ_REQ_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Get_Read_Block
��  �ܣ���ȡ��SPI�����϶��������ݿ�
��  ����pData�����������ݿ�洢��ַ
        Len�����ݿ鳤��
����ֵ��SPI_READ_COMPLETE    ����ȡ�ɹ�
        SPI_READ_NOT_COMPLETE����ȡʧ��
******************************************************************************/
uint8_t SPI_Master_Get_Read_Block(uint8_t *pData, uint8_t Len)
{
  uint8_t i;

  if (SPIDataBlock.Status != SPI_DATA_BLOCK_IDLE)
    return SPI_READ_NOT_COMPLETE;

  if (SPIDataBlock.ReadComplete)
  {
    SPIDataBlock.ReadComplete = 0;
    for (i = 0; i < Len; i++)
      pData[i] = SPIDataBlock.Data[i];

    return SPI_READ_COMPLETE;
  }

  return SPI_READ_NOT_COMPLETE;
}

/******************************************************************************
��������SPI_Master_Block_Transmit_ISR
��  �ܣ����ݿ鴫������жϺ���,���������ݿ鴫����ɺ����жϵ���
��  ������
����ֵ����
******************************************************************************/
#if SPI_CALL_DATA_BLOCK_TX_ISR
void SPI_Master_Block_Transmit_ISR(void)
{

}
#endif

#pragma CODE_SEG __NEAR_SEG NON_BANKED   	//�������жϺ�������FLASH�ķǷ�ҳ��

/******************************************************************************
��������SPI_ISR
��  �ܣ�SPI�жϷ�����,�����շ�����
��  ������
����ֵ����
******************************************************************************/
void interrupt SPI_ISR(void)
{
  if (SPIDataBlock.Status == SPI_DATA_BLOCK_WRITE)
  {
    if (SPISR_SPTEF)
    {
      SPIDataBlock.Ptr++;
      if (SPIDataBlock.Ptr < SPIDataBlock.Len)
        SPIDRL = SPIDataBlock.Data[SPIDataBlock.Ptr];
      else
      {
        SPICR1 &= 0xDF;                 //�رշ����ж�
        SPIDataBlock.Status = SPI_DATA_BLOCK_IDLE;
#if SPI_CALL_DATA_BLOCK_TX_ISR
        SPI_Master_Block_Transmit_ISR();
#endif
      }
    }
  }
  else if (SPIDataBlock.Status == SPI_DATA_BLOCK_READ)
  {
    if (SPISR_SPIF)
    {
      SPIDataBlock.Data[SPIDataBlock.Ptr] = SPIDRL;
      SPIDataBlock.Ptr++;
      if (SPIDataBlock.Ptr < SPIDataBlock.Len)
        SPIDRL = SPI_DUMMY_BYTE;
      else
      {
        SPICR1 &= 0x7F;                 //�رս����ж�
        SPIDataBlock.Status = SPI_DATA_BLOCK_IDLE;
        SPIDataBlock.ReadComplete = 1;  //�ý�����ɱ�־
      }
    }
  }
  else
  {
    if (SPISR_MODF)
      SPICR1 &= 0x7F;                   //�ر�SPI�ж�
  }
}

#pragma CODE_SEG DEFAULT