#define TRUE  1
#define FALSE 0
#define bool BYTE

#include "stm32l1xx_hal.h"
#include "diskio.h"
#include "fatfs_sd.h"
#include "main.h"


/* defines for the CS PIN */
#define SD_CS_GPIO_Port SPI1_CS_GPIO_Port
#define SD_CS_Pin SPI1_CS_Pin

/* manage your SPI handler below */
extern SPI_HandleTypeDef hspi1;

extern volatile uint8_t Timer1, Timer2;                    /* 10ms Timer decreasing every time */

static volatile DSTATUS Stat = STA_NOINIT;              /* Disc Status Flag*/
static uint8_t CardType;                                /* SD type 0:MMC, 1:SDC, 2:Block addressing */
static uint8_t PowerFlag = 0;                           /* Power condition Flag */


/* SPI Chip Select */
static void SELECT(void)
{
  HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET);
}

/* SPI Chip Deselect */
static void DESELECT(void)
{
  HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_SET);
}

/* SPI Transmit*/
static void SPI_TxByte(BYTE data)
{
  while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
  HAL_SPI_Transmit(&hspi1, &data, 1, SPI_TIMEOUT);
}

/* SPI Data send / receive return type function */
static uint8_t SPI_RxByte(void)
{
  uint8_t dummy, data;
  dummy = 0xFF;
  data = 0;
  
  while ((HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY));
  HAL_SPI_TransmitReceive(&hspi1, &dummy, &data, 1, SPI_TIMEOUT);
  
  return data;
}

/* SPI Data send / receive pointer type function*/
static void SPI_RxBytePtr(uint8_t *buff) 
{
  *buff = SPI_RxByte();
}

/* SD CARD Ready wait */
static uint8_t SD_ReadyWait(void) 
{
  uint8_t res;
  
  /* 500ms Counter preparation*/
  Timer2 = 50;

  SPI_RxByte();
  
  do
  {
    /* 0xFF SPI communication until a value is received */
    res = SPI_RxByte();
  } while ((res != 0xFF) && Timer2);
  
  return res;
}

/*Power on*/
static void SD_PowerOn(void) 
{
  uint8_t cmd_arg[6];
  uint32_t Count = 0x1FFF;
  

  DESELECT();
  
  for(int i = 0; i < 10; i++)
  {
    SPI_TxByte(0xFF);
  }
  
  /* SPI Chips Select */
  SELECT();
  
  /*  GO_IDLE_STATE State transitions*/
  cmd_arg[0] = (CMD0 | 0x40);
  cmd_arg[1] = 0;
  cmd_arg[2] = 0;
  cmd_arg[3] = 0;
  cmd_arg[4] = 0;
  cmd_arg[5] = 0x95;
  
  /* Command transmission*/
  for (int i = 0; i < 6; i++)
  {
    SPI_TxByte(cmd_arg[i]);
  }
  
  /* Answer waiting*/
  while ((SPI_RxByte() != 0x01) && Count)
  {
    Count--;
  }
  
  DESELECT();
  SPI_TxByte(0XFF);
  
  PowerFlag = 1;
}

/* Ä›Â â€žÄ›â€şďż˝ Ă«ďż˝â€žÄ™Â¸Â° */
static void SD_PowerOff(void) 
{
  PowerFlag = 0;
}

/* Ä›Â â€žÄ›â€şďż˝ Ä›ďż˝ďż˝Ă­ďż˝Ĺ› Ă­â„˘â€˘Ä›ĹĄÂ¸ */
static uint8_t SD_CheckPower(void) 
{
  /*  0=off, 1=on */
  return PowerFlag;
}

/* Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ° Ă­ĹšÂ¨Ă­â€šÂ· Ä›ďż˝ďż˝Ä›â€ąÂ  */
static bool SD_RxDataBlock(BYTE *buff, UINT btr) 
{
  uint8_t token;
  
  /* 100ms Ă­ďż˝â‚¬Ä›ĹĄÂ´Ă«Â¨Â¸ */
  Timer1 = 10;

  /* Ä›ĹĄâ€�Ă«â€ąÂµ Ă«Ĺšâ‚¬Ä™Â¸Â° */
  do 
  {    
    token = SPI_RxByte();
  } while((token == 0xFF) && Timer1);
  
  /* 0xFE Ä›ĹĄÂ´Ä›â„˘Â¸ Token Ä›ďż˝ďż˝Ä›â€ąÂ  Ä›â€ąĹ› Ä›â€”ďż˝Ă«ĹşÂ¬ Ä›Ë›ďż˝Ă«Â¦Â¬ */
  if(token != 0xFE)
    return FALSE;
  
  /* Ă«Ë›â€žĂ­Ĺ¤Ä˝Ä›â€”ďż˝ Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ° Ä›ďż˝ďż˝Ä›â€ąÂ  */
  do 
  {     
    SPI_RxBytePtr(buff++);
    SPI_RxBytePtr(buff++);
  } while(btr -= 2);
  
  SPI_RxByte(); /* CRC Ă«Â¬Â´Ä›â€ąĹ› */
  SPI_RxByte();
  
  return TRUE;
}

/* Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ° Ä›Â â€žÄ›â€ Ë‡ Ă­ĹšÂ¨Ă­â€šÂ· */
#if _READONLY == 0
static bool SD_TxDataBlock(const BYTE *buff, BYTE token)
{
  uint8_t resp;
  uint8_t wc;
  uint8_t i = 0;
    
  /* SDÄ›Ä…Â´Ă«â€śĹ› Ä›Â¤â‚¬Ă«Ä…â€ž Ă«Ĺšâ‚¬Ä™Â¸Â° */
  if (SD_ReadyWait() != 0xFF)
    return FALSE;
  
  /* Ă­â€ Â Ă­ďż˝Â° Ä›Â â€žÄ›â€ Ë‡ */
  SPI_TxByte(token);      
  
  /* Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ° Ă­â€ Â Ă­ďż˝Â°Ä›ĹĄÂ¸ Ä™Ë›ËťÄ›ĹˇÂ° */
  if (token != 0xFD) 
  { 
    wc = 0;
    
    /* 512 Ă«Â°â€ťÄ›ĹĄÂ´Ă­Ĺ Â¸ Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ° Ä›Â â€žÄ›â€ Ë‡ */
    do 
    { 
      SPI_TxByte(*buff++);
      SPI_TxByte(*buff++);
    } while (--wc);
    
    SPI_RxByte();       /* CRC Ă«Â¬Â´Ä›â€ąĹ› */
    SPI_RxByte();
    
    /* Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­Ĺ Â¸ Ä›ĹĄâ€�Ă«â€ąÂµ Ä›ďż˝ďż˝Ä›â€ąÂ  */
    while (i <= 64) 
    {			
      resp = SPI_RxByte();
      
      /* Ä›â€”ďż˝Ă«ĹşÂ¬ Ä›ĹĄâ€�Ă«â€ąÂµ Ä›Ë›ďż˝Ă«Â¦Â¬ */
      if ((resp & 0x1F) == 0x05) 
        break;
      
      i++;
    }
    
    /* SPI Ä›ďż˝ďż˝Ä›â€ąÂ  Ă«Ë›â€žĂ­Ĺ¤Ä˝ Clear */
    while (SPI_RxByte() == 0);
  }
  
  if ((resp & 0x1F) == 0x05)
    return TRUE;
  else
    return FALSE;
}
#endif /* _READONLY */

/* CMD Ă­ĹšÂ¨Ă­â€šÂ· Ä›Â â€žÄ›â€ Ë‡ */
static BYTE SD_SendCmd(BYTE cmd, DWORD arg) 
{
  uint8_t crc, res;
  
  /* SDÄ›Ä…Â´Ă«â€śĹ› Ă«Ĺšâ‚¬Ä™Â¸Â° */
  if (SD_ReadyWait() != 0xFF)
    return 0xFF;
  
  /* Ă«Ĺžâ€¦Ă«Â Ä… Ă­ĹšÂ¨Ă­â€šÂ· Ä›Â â€žÄ›â€ Ë‡ */
  SPI_TxByte(cmd); 			/* Command */
  SPI_TxByte((BYTE) (arg >> 24)); 	/* Argument[31..24] */
  SPI_TxByte((BYTE) (arg >> 16)); 	/* Argument[23..16] */
  SPI_TxByte((BYTE) (arg >> 8)); 	/* Argument[15..8] */
  SPI_TxByte((BYTE) arg); 		/* Argument[7..0] */
  
  /* Ă«Ĺžâ€¦Ă«Â Ä…Ă«Ĺ‚â€ž CRC Ä›Â¤â‚¬Ă«Ä…â€ž */
  crc = 0;  
  if (cmd == CMD0)
    crc = 0x95; /* CRC for CMD0(0) */
  
  if (cmd == CMD8)
    crc = 0x87; /* CRC for CMD8(0x1AA) */
  
  /* CRC Ä›Â â€žÄ›â€ Ë‡ */
  SPI_TxByte(crc);
  
  /* CMD12 Stop Reading Ă«Ĺžâ€¦Ă«Â Ä…Ä›ĹĄÂ¸ Ä™Ë›ËťÄ›ĹˇÂ°Ä›â€”ďż˝Ă«Ĺ â€ť Ä›ĹĄâ€�Ă«â€ąÂµ Ă«Â°â€ťÄ›ĹĄÂ´Ă­Ĺ Â¸ Ă­â€˘ďż˝Ă«â€šďż˝Ă«Ä„Ä˝ Ă«Ë›â€žĂ«Â¦Â°Ă«â€ąÂ¤ */
  if (cmd == CMD12)
    SPI_RxByte();
  
  /* 10Ă­ĹˇĹš Ă«â€šÂ´Ä›â€”ďż˝ Ä›Â â€˘Ä›ďż˝ďż˝ Ă«Ĺ¤Â°Ä›ĹĄÂ´Ă­â€žÂ°Ă«Ä„Ä˝ Ä›ďż˝ďż˝Ä›â€ąÂ Ă­â€˘Ĺ›Ă«â€ąÂ¤. */
  uint8_t n = 10; 
  do
  {
    res = SPI_RxByte();
  } while ((res & 0x80) && --n);
  
  return res;
}

/*-----------------------------------------------------------------------
  fatfsÄ›â€”ďż˝Ä›â€žĹ› Ä›â€šÂ¬Ä›ĹˇÂ©Ă«ďż˝ďż˝Ă«Ĺ â€ť Global Ă­â€˘Â¨Ä›ďż˝ďż˝Ă«â€śÂ¤
  user_diskio.c Ă­ĹšĹšÄ›ĹĄÄ˝Ä›â€”ďż˝Ä›â€žĹ› Ä›â€šÂ¬Ä›ĹˇÂ©Ă«ďż˝Ĺ›Ă«â€ąÂ¤.
-----------------------------------------------------------------------*/

/* SDÄ›Ä…Â´Ă«â€śĹ› Ä›Â´ďż˝Ä™Â¸Â°Ă­â„˘â€ť */
DSTATUS SD_disk_initialize(BYTE drv) 
{
  uint8_t n, type, ocr[4];
  
  /* Ă­â€˘Ĺ›Ä›Ë�â€¦Ă«Ä„ďż˝Ä›ĹĄďż˝ Ă«â€śĹ›Ă«ĹĄÄ˝Ä›ĹĄÂ´Ă«Â¸ĹšĂ«Â§Ĺš Ä›Â§â‚¬Ä›â€şďż˝ */
  if(drv)
    return STA_NOINIT;  
  
  /* SDÄ›Ä…Â´Ă«â€śĹ› Ă«Ĺ»Â¸Ä›â€šËťÄ›Ĺľâ€¦ */
  if(Stat & STA_NODISK)
    return Stat;        
  
  /* SDÄ›Ä…Â´Ă«â€śĹ› Power On */
  SD_PowerOn();         
  
  /* SPI Ă­â€ ÂµÄ›â€ąÂ Ä›ĹĄâ€ž Ä›Ĺ›â€žĂ­â€˘Â´ Chip Select */
  SELECT();             
  
  /* SDÄ›Ä…Â´Ă«â€śĹ› Ă­ďż˝â‚¬Ä›Ĺľâ€¦Ă«Ĺ‚â‚¬Ä›ďż˝ďż˝ Ä›Â´ďż˝Ä™Â¸Â°Ă­â„˘â€ť */
  type = 0;
  
  /* Idle Ä›ďż˝ďż˝Ă­ďż˝Ĺ› Ä›Â§â€žÄ›Ĺľâ€¦ */
  if (SD_SendCmd(CMD0, 0) == 1) 
  { 
    /* Ă­ďż˝â‚¬Ä›ĹĄÂ´Ă«Â¨Â¸ 1Ä›Â´ďż˝ Ä›â€žÂ¤Ä›Â â€˘ */
    Timer1 = 100;
    
    /* SD Ä›ĹĄÂ¸Ă­â€žÂ°Ă­Ĺ˝ďż˝Ä›ĹĄÂ´Ä›Ĺ Â¤ Ă«Ĺąâ„˘Ä›Ĺľâ€� Ä›Ë‡Â°Ä™Â±Â´ Ă­â„˘â€˘Ä›ĹĄÂ¸ */
    if (SD_SendCmd(CMD8, 0x1AA) == 1) 
    { 
      /* SDC Ver2+ */
      for (n = 0; n < 4; n++)
      {
        ocr[n] = SPI_RxByte();
      }
      
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) 
      { 
        /* 2.7-3.6V Ä›Â â€žÄ›â€˘â€˘Ă«Ë›â€ťÄ›Ĺ›â€ž Ă«Ĺąâ„˘Ä›Ĺľâ€� */
        do {
          if (SD_SendCmd(CMD55, 0) <= 1 && SD_SendCmd(CMD41, 1UL << 30) == 0)
            break; /* ACMD41 with HCS bit */
        } while (Timer1);
        
        if (Timer1 && SD_SendCmd(CMD58, 0) == 0) 
        { 
          /* Check CCS bit */
          for (n = 0; n < 4; n++)
          {
            ocr[n] = SPI_RxByte();
          }
          
          type = (ocr[0] & 0x40) ? 6 : 2;
        }
      }
    } 
    else 
    { 
      /* SDC Ver1 or MMC */
      type = (SD_SendCmd(CMD55, 0) <= 1 && SD_SendCmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
      
      do {
        if (type == 2) 
        {
          if (SD_SendCmd(CMD55, 0) <= 1 && SD_SendCmd(CMD41, 0) == 0)
            break; /* ACMD41 */
        } 
        else 
        {
          if (SD_SendCmd(CMD1, 0) == 0)
            break; /* CMD1 */
        }
      } while (Timer1);
      
      if (!Timer1 || SD_SendCmd(CMD16, 512) != 0) 
      {
        /* Ă«Â¸â€ťĂ«ĹşÂ­ Ä™Â¸Â¸Ä›ĹĄÂ´ Ä›â€žÂ Ă­ďż˝ĹĄ */
        type = 0;
      }
    }
  }
  
  CardType = type;
  
  DESELECT();
  
  SPI_RxByte(); /* Idle Ä›ďż˝ďż˝Ă­ďż˝Ĺ› Ä›Â â€žĂ­â„˘ďż˝ (Release DO) */
  
  if (type) 
  {
    /* Clear STA_NOINIT */
    Stat &= ~STA_NOINIT; 
  }
  else
  {
    /* Initialization failed */
    SD_PowerOff();
  }
  
  return Stat;
}

/* Ă«â€ťâ€ťÄ›Ĺ Â¤Ă­ďż˝Â¬ Ä›ďż˝ďż˝Ă­ďż˝Ĺ› Ă­â„˘â€˘Ä›ĹĄÂ¸ */
DSTATUS SD_disk_status(BYTE drv) 
{
  if (drv)
    return STA_NOINIT; 
  
  return Stat;
}

/* Ä›â€žÄ…Ă­â€žÂ° Ä›ĹĄËťÄ™Â¸Â° */
DRESULT SD_disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) 
{
  if (pdrv || !count)
    return RES_PARERR;
  
  if (Stat & STA_NOINIT)
    return RES_NOTRDY;
  
  if (!(CardType & 4))
    sector *= 512;      /* Ä›Â§â‚¬Ä›Â â€˘ sectorĂ«Ä„Ä˝ Byte addressing Ă«â€ąÂ¨Ä›Ĺ›â€žĂ«Ë‡Ĺ› Ă«Ĺ‚â‚¬Ä™Ë›Ëť */
  
  SELECT();
  
  if (count == 1) 
  { 
    /* Ä›â€ąÂ±Ä™Â¸â‚¬ Ă«Â¸â€ťĂ«Ë‡ĹĄ Ä›ĹĄËťÄ™Â¸Â° */
    if ((SD_SendCmd(CMD17, sector) == 0) && SD_RxDataBlock(buff, 512))
      count = 0;
  } 
  else 
  { 
    /* Ă«â€ąÂ¤Ä›Â¤â€� Ă«Â¸â€ťĂ«Ë‡ĹĄ Ä›ĹĄËťÄ™Â¸Â° */
    if (SD_SendCmd(CMD18, sector) == 0) 
    {       
      do {
        if (!SD_RxDataBlock(buff, 512))
          break;
        
        buff += 512;
      } while (--count);
      
      /* STOP_TRANSMISSION, Ă«ĹžÂ¨Ă«â€śÂ  Ă«Â¸â€ťĂ«ĹşÂ­Ä›ĹĄâ€ž Ă«â€ąÂ¤ Ä›ĹĄËťÄ›ĹĄâ‚¬ Ă­â€şâ€ž, Ä›Â â€žÄ›â€ Ë‡ Ä›Â¤â€�Ä›Â§â‚¬ Ä›Ĺˇâ€ťÄ›Ë›Â­ */
      SD_SendCmd(CMD12, 0); 
    }
  }
  
  DESELECT();
  SPI_RxByte(); /* Idle Ä›ďż˝ďż˝Ă­ďż˝Ĺ›(Release DO) */
  
  return count ? RES_ERROR : RES_OK;
}

/* Ä›â€žÄ…Ă­â€žÂ° Ä›â€śÂ°Ä™Â¸Â° */
#if _READONLY == 0
DRESULT SD_disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) 
{
  if (pdrv || !count)
    return RES_PARERR;
  
  if (Stat & STA_NOINIT)
    return RES_NOTRDY;
  
  if (Stat & STA_PROTECT)
    return RES_WRPRT;
  
  if (!(CardType & 4))
    sector *= 512; /* Ä›Â§â‚¬Ä›Â â€˘ sectorĂ«Ä„Ä˝ Byte addressing Ă«â€ąÂ¨Ä›Ĺ›â€žĂ«Ë‡Ĺ› Ă«Ĺ‚â‚¬Ä™Ë›Ëť */
  
  SELECT();
  
  if (count == 1) 
  { 
    /* Ä›â€ąÂ±Ä™Â¸â‚¬ Ă«Â¸â€ťĂ«Ë‡ĹĄ Ä›â€śÂ°Ä™Â¸Â° */
    if ((SD_SendCmd(CMD24, sector) == 0) && SD_TxDataBlock(buff, 0xFE))
      count = 0;
  } 
  else 
  { 
    /* Ă«â€ąÂ¤Ä›Â¤â€� Ă«Â¸â€ťĂ«Ë‡ĹĄ Ä›â€śÂ°Ä™Â¸Â° */
    if (CardType & 2) 
    {
      SD_SendCmd(CMD55, 0);
      SD_SendCmd(CMD23, count); /* ACMD23 */
    }
    
    if (SD_SendCmd(CMD25, sector) == 0) 
    {       
      do {
        if(!SD_TxDataBlock(buff, 0xFC))
          break;
        
        buff += 512;
      } while (--count);
      
      if(!SD_TxDataBlock(0, 0xFD))
      {        
        count = 1;
      }
    }
  }
  
  DESELECT();
  SPI_RxByte();
  
  return count ? RES_ERROR : RES_OK;
}
#endif /* _READONLY */

/* Ä™Â¸Â°Ă­ďż˝â‚¬ Ă­â€˘Â¨Ä›ďż˝ďż˝ */
DRESULT SD_disk_ioctl(BYTE drv, BYTE ctrl, void *buff) 
{
  DRESULT res;
  BYTE n, csd[16], *ptr = buff;
  WORD csize;
  
  if (drv)
    return RES_PARERR;
  
  res = RES_ERROR;
  
  if (ctrl == CTRL_POWER) 
  {
    switch (*ptr) 
    {
    case 0:
      if (SD_CheckPower())
        SD_PowerOff();          /* Power Off */
      res = RES_OK;
      break;
    case 1:
      SD_PowerOn();             /* Power On */
      res = RES_OK;
      break;
    case 2:
      *(ptr + 1) = (BYTE) SD_CheckPower();
      res = RES_OK;             /* Power Check */
      break;
    default:
      res = RES_PARERR;
    }
  } 
  else 
  {
    if (Stat & STA_NOINIT)
      return RES_NOTRDY;
    
    SELECT();
    
    switch (ctrl) 
    {
    case GET_SECTOR_COUNT: 
      /* SDÄ›Ä…Â´Ă«â€śĹ› Ă«â€šÂ´ SectorÄ›ĹĄďż˝ Ä™Â°Ĺ›Ä›ďż˝ďż˝ (DWORD) */
      if ((SD_SendCmd(CMD9, 0) == 0) && SD_RxDataBlock(csd, 16)) 
      {
        if ((csd[0] >> 6) == 1) 
        { 
          /* SDC ver 2.00 */
          csize = csd[9] + ((WORD) csd[8] << 8) + 1;
          *(DWORD*) buff = (DWORD) csize << 10;
        } 
        else 
        { 
          /* MMC or SDC ver 1.XX */
          n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
          csize = (csd[8] >> 6) + ((WORD) csd[7] << 2) + ((WORD) (csd[6] & 3) << 10) + 1;
          *(DWORD*) buff = (DWORD) csize << (n - 9);
        }
        
        res = RES_OK;
      }
      break;
      
    case GET_SECTOR_SIZE: 
      /* Ä›â€žÄ…Ă­â€žÂ°Ä›ĹĄďż˝ Ă«â€ąÂ¨Ä›Ĺ›â€ž Ă­ďż˝Â¬Ä™Â¸Â° (WORD) */
      *(WORD*) buff = 512;
      res = RES_OK;
      break;
      
    case CTRL_SYNC: 
      /* Ä›â€śÂ°Ä™Â¸Â° Ă«Ĺąâ„˘Ä™Â¸Â°Ă­â„˘â€ť */
      if (SD_ReadyWait() == 0xFF)
        res = RES_OK;
      break;
      
    case MMC_GET_CSD: 
      /* CSD Ä›Â â€˘Ă«Ĺ‚Â´ Ä›ďż˝ďż˝Ä›â€ąÂ  (16 bytes) */
      if (SD_SendCmd(CMD9, 0) == 0 && SD_RxDataBlock(ptr, 16))
        res = RES_OK;
      break;
      
    case MMC_GET_CID: 
      /* CID Ä›Â â€˘Ă«Ĺ‚Â´ Ä›ďż˝ďż˝Ä›â€ąÂ  (16 bytes) */
      if (SD_SendCmd(CMD10, 0) == 0 && SD_RxDataBlock(ptr, 16))
        res = RES_OK;
      break;
      
    case MMC_GET_OCR: 
      /* OCR Ä›Â â€˘Ă«Ĺ‚Â´ Ä›ďż˝ďż˝Ä›â€ąÂ  (4 bytes) */
      if (SD_SendCmd(CMD58, 0) == 0) 
      {         
        for (n = 0; n < 4; n++)
        {
          *ptr++ = SPI_RxByte();
        }
        
        res = RES_OK;
      }     
      break;//asi newim
      
    default:
      res = RES_PARERR;
    }
    
    DESELECT();
    SPI_RxByte();
  }
  
  return res;
}
