/** ###################################################################
**     THIS COMPONENT MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
**     Filename    : SS1.c
**     Project     : ProcessorExpert
**     Processor   : MC56F84789VLL
**     Component   : SynchroSlave
**     Version     : Component 02.249, Driver 02.04, CPU db: 3.50.001
**     Compiler    : Metrowerks DSP C Compiler
**     Date/Time   : 2012-07-05, 13:51, # CodeGen: 41
**     Abstract    :
**         This component "SynchroSlave" implements SLAVE part of synchronous
**         serial master-slave communication.
**     Settings    :
**         Synchro type                : SLAVE
**
**         Serial channel              : QSPI2
**
**         Protocol
**             Clock edge              : rising
**             Width                   : 8 bits
**             Empty character         : 32
**             Empty char. on input    : RECEIVED
**
**         Registers
**             Input buffer            : QSPI2_SPDRR [57554]
**             Output buffer           : QSPI2_SPDTR [57555]
**             Control register        : QSPI2_SPSCR [57552]
**             Mode register           : QSPI2_SPDSR [57553]
**             Baud setting reg.       : QSPI2_SPSCR [57552]
**
**         Input interrupt
**             Vector name             : INT_QSPI2_RCV
**             Priority                : 1
**
**         Output interrupt
**             Vector name             : INT_QSPI2_XMIT
**             Priority                : 1
**
**         Used pins                   :
**         ----------------------------------------------------------
**              Function    | On package |    Name
**         ----------------------------------------------------------
**               Input      |     40     |  GPIOB10/ANC22/XB_IN8/MOSI2
**               Output     |     39     |  GPIOB9/ANC21/XB_IN9/MISO2
**               Clock      |     41     |  GPIOB11/ANC23/XB_IN7/SCK2
**           Select slave   |     51     |  GPIOG10/PWMB_2X/PWMA_2X/XB_IN8/SS2_B
**         ----------------------------------------------------------
**     Contents    :
**         RecvChar        - byte SS1_RecvChar(SS1_TComData *Chr);
**         SendChar        - byte SS1_SendChar(SS1_TComData Chr);
**         RecvBlock       - byte SS1_RecvBlock(SS1_TComData *Ptr, word Size, word *Rcv);
**         SendBlock       - byte SS1_SendBlock(SS1_TComData *Ptr, word Size, word *Snd);
**         ClearRxBuf      - byte SS1_ClearRxBuf(void);
**         ClearTxBuf      - byte SS1_ClearTxBuf(void);
**         GetCharsInRxBuf - word SS1_GetCharsInRxBuf(void);
**         GetCharsInTxBuf - word SS1_GetCharsInTxBuf(void);
**         GetError        - byte SS1_GetError(SS1_TError *Err);
**
**     Copyright : 1997 - 2012 Freescale Semiconductor, Inc. All Rights Reserved.
**     
**     http      : www.freescale.com
**     mail      : support@freescale.com
** ###################################################################*/

/* MODULE SS1. */

#include "Events.h"
#include "SS1.h"

#define OVERRUN_ERR      1U            /* Overrun error flag bit   */
#define CHAR_IN_RX       8U            /* Char is in RX buffer     */
#define FULL_TX          16U           /* Full transmit buffer     */
#define RUNINT_FROM_TX   32U           /* Interrupt is in progress */
#define FULL_RX          64U           /* Full receive buffer      */

static byte SerFlag;                   /* Flags for serial communication */
                                       /* Bits: 0 - OverRun error */
                                       /*       1 - Unused */
                                       /*       2 - Unused */
                                       /*       3 - Char in RX buffer */
                                       /*       4 - Full TX buffer */
                                       /*       5 - Running int from TX */
                                       /*       6 - Full RX buffer */
                                       /*       7 - Unused */
static byte ErrFlag;                   /* Error flags for GetError method */
volatile word SS1_InpLen;              /* Length of input buffer's content */
static SS1_TComData *InpPtrR;          /* Pointer for reading from input buffer */
static SS1_TComData *InpPtrW;          /* Pointer for writing to input buffer */
static SS1_TComData InpBuffer[SS1_INP_BUF_SIZE]; /* Input buffer SPI commmunication */
volatile word SS1_OutLen;              /* Length of output bufer's content */
static SS1_TComData *OutPtrR;          /* Pointer for reading from output buffer */
static SS1_TComData *OutPtrW;          /* Pointer for writing to output buffer */
static SS1_TComData OutBuffer[SS1_OUT_BUF_SIZE]; /* Output buffer for SPI commmunication */

/*
** ===================================================================
**     Method      :  SS1_RecvChar (component SynchroSlave)
**
**     Description :
**         If any data is received, this method returns one character,
**         otherwise it returns an error code (it does not wait for
**         data). 
**         For information about SW overrun behavior please see
**         <General info page>.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on selected CPU and receiver
**         is configured to use DMA controller then this method only
**         sets the selected DMA channel. Status of the DMA transfer
**         can then be checked using method GetCharsInRxBuf. See
**         typical usage for details about communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Chr             - A pointer to the received character
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_RXEMPTY - No data in receiver
**                           ERR_OVERRUN - Overrun error is detected
**                           from the last char or block received. In
**                           polling mode, this error code is returned
**                           only when the hardware supports detection
**                           of the overrun error. 
**                           ERR_FAULT - Fault error was detected from
**                           the last char or block received. This error
**                           does not need to be supported on some Cpu
**                           (see generated code).
** ===================================================================
*/
byte SS1_RecvChar(SS1_TComData *Chr)
{
  register byte FlagTmp;

  if (SS1_InpLen > 0U) {               /* Is number of received chars greater than 0? */
    EnterCritical();                   /* Disable global interrupts */
    SS1_InpLen--;                      /* Decrease number of received chars */
    *Chr = *(InpPtrR++);               /* Read the char */
    /*lint -save  -e946 Disable MISRA rule (17.2) checking. */
    if (InpPtrR >= (InpBuffer + SS1_INP_BUF_SIZE)) { /* Is the pointer out of the receive buffer? */
      InpPtrR = InpBuffer;             /* Set pointer to the first item into the receive buffer */
    }
    /*lint -restore Enable MISRA rule (17.2) checking. */
    FlagTmp = SerFlag;                 /* Safe the flags */
    SerFlag &= (byte)~(OVERRUN_ERR | FULL_RX); /* Clear flag "char in RX buffer" */
    ExitCritical();                    /* Enable global interrupts */
  }
  else {
      return ERR_RXEMPTY;              /* Receiver is empty */
  }
  if ((FlagTmp & (byte)(OVERRUN_ERR | FULL_RX)) != 0U) { /* Is the overrun occured? */
    return ERR_OVERRUN;                /* If yes then return error */
  }
  else {
    return ERR_OK;
  }
}

/*
** ===================================================================
**     Method      :  SS1_SendChar (component SynchroSlave)
**
**     Description :
**         Sends one character to the channel.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         transmitter is configured to use DMA controller then this
**         method only sets the selected DMA channel. The status of the
**         DMA transfer can then be checked using GetCharsInTxBuf
**         method. See the typical usage for details about
**         communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Chr             - Character to send
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_DISABLED -  Device is disabled (only if
**                           output DMA is supported and enabled)
**                           ERR_TXFULL - Transmitter is full
** ===================================================================
*/
byte SS1_SendChar(SS1_TComData Chr)
{
  if (SS1_OutLen == SS1_OUT_BUF_SIZE) { /* Is number of chars in buffer the same as the size of transmit buffer? */
    return ERR_TXFULL;                 /* If yes then error */
  }
  EnterCritical();                     /* Disable global interrupts */
  SS1_OutLen++;                        /* Increase number of bytes in the transmit buffer */
  *(OutPtrW++) = Chr;                  /* Store char to buffer */
  /*lint -save  -e946 Disable MISRA rule (17.2) checking. */
  if (OutPtrW >= (OutBuffer + SS1_OUT_BUF_SIZE)) { /* Is the pointer out of the transmit buffer? */
    OutPtrW = OutBuffer;               /* Set pointer to the first item in the transmit buffer */
  }
  /*lint -restore Enable MISRA rule (17.2) checking. */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  SS1_RecvBlock (component SynchroSlave)
**
**     Description :
**         If any data received, this method returns the block of the
**         data and its length (and incidental error), otherwise it
**         returns error code (it does not wait for data).
**         If less than requested number of characters is received only
**         the available data is copied from the receive buffer to the
**         user specified destination and the ERR_EXEMPTY value is
**         returned.
**         This method is available only if non-zero length of input
**         buffer is defined. 
**         For information about SW overrun behavior please see
**         <General info page>.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         receiver is configured to use DMA controller then this
**         method only sets the selected DMA channel. The status of the
**         DMA transfer can then be checked using GetCharsInRxBuf
**         method. See the typical usage for details about
**         communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Ptr             - A pointer to the block of received data
**         Size            - The size of the block
**       * Rcv             - Pointer to a variable where an actual
**                           number of copied characters is stored
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_RXEMPTY - It was not possible to read
**                           requested number of bytes from the buffer
**                           ERR_FAULT - Fault error was detected from
**                           the last char or block received. This error
**                           does not need to be supported on some Cpu
**                           (see generated code).
** ===================================================================
*/
byte SS1_RecvBlock(SS1_TComData *Ptr,word Size,word *Rcv)
{
  register word count;                 /* Number of received chars */
  register byte Result = ERR_OK;       /* Most serious error */
  register byte ResultTmp;             /* Last error */

  count = 0U;
  while (count < Size) {
    ResultTmp = SS1_RecvChar(Ptr++);   /* Receive one character */
    if (ResultTmp > Result) {          /* Is last error most serious than through error state? */
      Result = ResultTmp;              /* If yes then prepare error value to return */
    }
    if ((ResultTmp != ERR_OK)&&(ResultTmp != ERR_OVERRUN)) { /* Receiving given number of chars */
      break;                           /* Break data block receiving */
    }
    count++;
  }
  *Rcv = count;                        /* Return number of received chars */
  return Result;                       /* Return most serious error */
}

/*
** ===================================================================
**     Method      :  SS1_SendBlock (component SynchroSlave)
**
**     Description :
**         Sends a block of characters to the channel. This method is
**         only available if a non-zero length of output buffer is
**         defined.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and
**         transmitter is configured to use DMA controller then this
**         method only sets the selected DMA channel. The status of the
**         DMA transfer can then be checked using GetCharsInTxBuf
**         method. See the typical usage for details about
**         communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Ptr             - Pointer to the block of data to send
**         Size            - Size of the block
**       * Snd             - Pointer to number of data that are sent
**                           (moved to buffer)
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_DISABLED -  Device is disabled (only if
**                           output DMA is supported and enabled)
**                           ERR_TXFULL - It was not possible to send
**                           requested number of bytes
** ===================================================================
*/
byte SS1_SendBlock(SS1_TComData *Ptr,word Size,word *Snd)
{
  register word count;                 /* Number of sent chars */
  register byte Result = ERR_OK;       /* Last error */
  SS1_TComData *TmpPtr = Ptr;          /* Temporary output buffer pointer */

  for (count = 0U; count < Size; count++) {
    Result = SS1_SendChar(*TmpPtr++);  /* Send one character */
    if (Result != ERR_OK) {            /* Sending given number of chars */
      break;                           /* Break data block sending */
    }
  }
  *Snd = count;                        /* Return number of sended chars */
  return Result;                       /* Return error code */
}

/*
** ===================================================================
**     Method      :  SS1_ClearRxBuf (component SynchroSlave)
**
**     Description :
**         Clears the receive buffer. This method is available only if
**         a non-zero length of input buffer is defined.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         receiver is configured to use DMA controller then this
**         method only stops the selected DMA channel.
**     Parameters  : None
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
** ===================================================================
*/
byte SS1_ClearRxBuf(void)
{
  EnterCritical();                     /* Disable global interrupts */
  SS1_InpLen = 0U;                     /* Set number of chars in the transmit buffer to 0 */
  InpPtrW = InpBuffer;                 /* Set pointers on the first item in the transmit buffer */
  InpPtrR = InpBuffer;
  SerFlag &= (byte)~(OVERRUN_ERR | FULL_RX); /* Clear flags */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  SS1_ClearTxBuf (component SynchroSlave)
**
**     Description :
**         Clears the transmit buffer. This method is only available if
**         a non-zero length of output buffer is defined.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         transmitter is configured to use DMA controller then this
**         method only stops the selected DMA channel.
**     Parameters  : None
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
** ===================================================================
*/
byte SS1_ClearTxBuf(void)
{
  EnterCritical();                     /* Disable global interrupts */
  SS1_OutLen = 0U;                     /* Set number of chars in the receive buffer to 0 */
  OutPtrW = OutBuffer;                 /* Set pointers on the first item in the receive buffer */
  OutPtrR = OutBuffer;
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  SS1_GetCharsInRxBuf (component SynchroSlave)
**
**     Description :
**         Returns the number of characters in the input buffer.
**         Note: If the Interrupt service is disabled, and the Ignore
**         empty character is set to yes, and a character has been
**         received, then this method returns 1 although it was an
**         empty character.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         receiver is configured to use DMA controller then this
**         method returns the number of characters in the receive
**         buffer.
**     Parameters  : None
**     Returns     :
**         ---             - Number of characters in the input buffer.
** ===================================================================
*/
/*
word SS1_GetCharsInRxBuf(void)

**      This method is implemented as a macro. See header module. **
*/

/*
** ===================================================================
**     Method      :  SS1_GetCharsInTxBuf (component SynchroSlave)
**
**     Description :
**         Returns the number of characters in the output buffer.
**         [ Version specific information for Freescale 56800
**         derivatives ] 
**         DMA mode:
**         If DMA controller is available on the selected CPU and the
**         transmitter is configured to use DMA controller then this
**         method returns the number of characters in the transmit
**         buffer.
**     Parameters  : None
**     Returns     :
**         ---             - Number of characters in the output buffer.
** ===================================================================
*/
/*
word SS1_GetCharsInTxBuf(void)

**      This method is implemented as a macro. See header module. **
*/

/*
** ===================================================================
**     Method      :  SS1_GetError (component SynchroSlave)
**
**     Description :
**         Returns a set of errors on the channel (errors that cannot
**         be returned in given methods). The component accumulates
**         errors in a set; after calling [GetError] this set is
**         returned and cleared. This method is available only if the
**         "Interrupt service/event" property is enabled.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Err             - A pointer to the returned set of errors
**     Returns     :
**         ---             - Error code (if GetError did not succeed),
**                           possible codes:
**                           ERR_OK - OK
** ===================================================================
*/
byte SS1_GetError(SS1_TError *Err)
{
  EnterCritical();                     /* Disable global interrupts */
  Err->err = 0U;
  Err->errName.OverRun = (((ErrFlag & OVERRUN_ERR) != 0U) ? 1U:0U); /* Overrun error */
  Err->errName.RxBufOvf = (((ErrFlag & FULL_RX) != 0U) ? 1U:0U); /* Buffer overflow */
  ErrFlag = 0U;                        /* Reset error flags */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  SS1_InterruptRx (component SynchroSlave)
**
**     Description :
**         The method services the interrupt of the selected peripheral(s)
**         and eventually invokes the beans event(s).
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
#define ON_ERROR       1U
#define ON_FULL_RX     2U
#define ON_RX_CHAR     4U
#define ON_FREE_TX     8U
#define ON_TX_CHAR     16U
#define ON_EMPTY_CHAR  32U
#define ON_RX_CHAR_EXT 64U
#pragma interrupt alignsp saveall
void SS1_InterruptRx(void)
{
  register word Data;                  /* Temporary variable for data */
  register byte Flags = 0U;            /* Temporary variable for flags */
  register word Status;                /* Temporary variable for flags */

  Status = getReg(QSPI2_SPSCR);        /* Read the device error register */
  Data = getReg(QSPI2_SPDRR);          /* Read data from receiver */
  if (getRegBit(QSPI2_SPSCR,OVRF)) {   /* Occured any overflow condition between QSPI2_SPSCR and QSPI2_SPDRR reading? */
    getReg(QSPI2_SPDRR);               /* Clear the overflow flag */
    Status |= QSPI2_SPSCR_OVRF_MASK;   /* Set overrun flag */
  }
  if (Status & QSPI2_SPSCR_OVRF_MASK) { /* Occured any overflow condition? */
    SerFlag |= (OVERRUN_ERR);          /* Set the OnError flag */
    ErrFlag |= (OVERRUN_ERR);          /* If yes then set the Error flag for GetError method */
  }
  if (SS1_InpLen < SS1_INP_BUF_SIZE) { /* Is number of bytes in the receive buffer lower than size of buffer? */
    SS1_InpLen++;                      /* Increse number of chars in the receive buffer */
    *(InpPtrW)++ = (SS1_TComData)Data; /* Save received char to the receive buffer */
    /*lint -save  -e946 Disable MISRA rule (17.2) checking. */
    if (InpPtrW >= (InpBuffer + SS1_INP_BUF_SIZE)) { /* Is the pointer out of the receive buffer? */
      InpPtrW = InpBuffer;             /* Set pointer on the first item into the receive buffer */
    }
    /*lint -restore Enable MISRA rule (17.2) checking. */
    Flags |= ON_RX_CHAR;               /* If yes then set the OnRxChar flag */
    if (SS1_InpLen == SS1_INP_BUF_SIZE) { /* Is number of bytes in the receive buffer equal to the size of buffer? */
      Flags |= ON_FULL_RX;             /* Set flag "OnRXChar" */
    }
  }
  else {
    SerFlag |= (FULL_RX);              /* Set flag "full RX buffer" */
    ErrFlag |= (FULL_RX);              /* Set flag "full RX buffer" for GetError method */
  }
  if (SS1_OutLen) {                    /* Is number of bytes in the transmit buffer greather then 0? */
    SS1_OutLen--;                      /* Decrease number of chars in the transmit buffer */
    setReg(QSPI2_SPDTR,*(OutPtrR++));  /* Store char to transmitter register */
    /*lint -save  -e946 Disable MISRA rule (17.2) checking. */
    if (OutPtrR >= (OutBuffer + SS1_OUT_BUF_SIZE)) { /* Is the pointer out of the transmit buffer? */
      OutPtrR = OutBuffer;             /* Set pointer on the first item into the transmit buffer */
    }
    /*lint -restore Enable MISRA rule (17.2) checking. */
    Flags |= ON_TX_CHAR;               /* Set the OnTXChar flag */
    if (SS1_OutLen==0U) {              /* Is the transmit buffer empty? */
      Flags |= ON_FREE_TX;             /* Set the OnFreeTXBuf flag */
    }
  }
  else {
    setReg(QSPI2_SPDTR,SS1_EOF);       /* Store the empty char to the transmit register */
  }
  if (Flags & ON_RX_CHAR) {            /* Is OnRxChar flag set? */
    SS1_OnRxChar();                    /* Invoke user event */
  }
  if (Flags & ON_FULL_RX) {            /* Is OnTxChar flag set? */
    SS1_OnFullRxBuf();                 /* Invoke user event */
  }
  if (Flags & ON_TX_CHAR) {            /* Is OnTxChar flag set? */
    SS1_OnTxChar();                    /* Invoke user event */
  }
  if (Flags & ON_FREE_TX) {            /* Is OnFreeTxBuf flag set? */
    SS1_OnFreeTxBuf();                 /* Invoke user event */
  }
}

/*
** ===================================================================
**     Method      :  SS1_Init (component SynchroSlave)
**
**     Description :
**         Initializes the associated peripheral(s) and the beans 
**         internal variables. The method is called automatically as a 
**         part of the application initialization code.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
void SS1_Init(void)
{
  /* QSPI2_SPSCR: SPR=0,DSO=1,ERRIE=0,MODFEN=0,SPRIE=0,SPMSTR=0,CPOL=0,CPHA=1,SPE=0,SPTIE=0,SPRF=0,OVRF=0,MODF=1,SPTE=0 */
  setReg(QSPI2_SPSCR,4162);            /* Set control register */
  /* QSPI2_SPDSR: WOM=0,TDMAEN=0,RDMAEN=0,BD2X=0,SSB_IN=0,SSB_DATA=0,SSB_ODM=0,SSB_AUTO=0,SSB_DDR=0,SSB_STRB=0,SSB_OVER=0,SPR3=0,DS=7 */
  setReg(QSPI2_SPDSR,7);               /* Set data size and control register */
  SerFlag = 0U;                        /* Reset all flags */
  ErrFlag = 0U;                        /* Reset all flags in mirror */
  SS1_InpLen = 0U;                     /* No char in the receive buffer */
  InpPtrR = InpBuffer;                 /* Set pointer on the first item in the receive buffer */
  InpPtrW = InpBuffer;
  SS1_OutLen = 0U;                     /* No char in the transmit buffer */
  OutPtrR = OutBuffer;                 /* Set pointer on the first item in the transmit buffer */
  OutPtrW = OutBuffer;
  setRegBit(QSPI2_SPSCR,SPE);          /* Enable device */
  setReg(QSPI2_SPDTR,SS1_EOF);         /* Store the empty char to the transmit register */
  setRegBits(QSPI2_SPSCR,(QSPI2_SPSCR_ERRIE_MASK|QSPI2_SPSCR_SPRIE_MASK)); /* Enable receive and error interrupts */
}

/* END SS1. */

/*
** ###################################################################
**
**     This file was created by Processor Expert 5.3 [05.01]
**     for the Freescale 56800 series of microcontrollers.
**
** ###################################################################
*/
