/** ###################################################################
**     THIS BEAN MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
**     Filename  : AS1.C
**     Project   : sci_echo
**     Processor : MC56F8006_48_LQFP
**     Beantype  : AsynchroSerial
**     Version   : Bean 02.455, Driver 02.01, CPU db: 3.00.177
**     Compiler  : Metrowerks DSP C Compiler
**     Date/Time : 11/15/2008, 9:17 PM
**     Abstract  :
**         This bean "AsynchroSerial" implements an asynchronous serial
**         communication. The bean supports different settings of
**         parity, word width, stop-bit and communication speed,
**         user can select interrupt or polling handler.
**         Communication speed can be changed also in runtime.
**         The bean requires one on-chip asynchronous serial channel.
**     Settings  :
**         Serial channel              : SCI
**
**         Protocol
**             Init baud rate          : 36800baud
**             Width                   : 8 bits
**             Stop bits               : 1
**             Parity                  : none
**             Breaks                  : Disabled
**             Input buffer size       : 2
**             Output buffer size      : 2
**
**         Registers
**             Input buffer            : SCI_DATA  [F0E4]
**             Output buffer           : SCI_DATA  [F0E4]
**             Control register        : SCI_CTRL1 [F0E1]
**             Mode register           : SCI_CTRL1 [F0E1]
**             Baud setting reg.       : SCI_RATE  [F0E0]
**
**         Input interrupt
**             Vector name             : INT_SCI_Rx_Full_Over_Error
**             Priority                : 0
**
**         Output interrupt
**             Vector name             : INT_SCI_Tx_Empty_Idle
**             Priority                : 0
**
**         Used pins:
**         ----------------------------------------------------------
**           Function | On package           |    Name
**         ----------------------------------------------------------
**            Input   |     1                |  GPIOB6_ANA13_SDA_RXD_CMP0_P2_CLKIN
**            Output  |     3                |  GPIOB7_ANA11_SCL_TXD_CMP2_M3
**         ----------------------------------------------------------
**
**
**
**     Contents  :
**         RecvChar        - byte AS1_RecvChar(AS1_TComData *Chr);
**         SendChar        - byte AS1_SendChar(AS1_TComData Chr);
**         RecvBlock       - byte AS1_RecvBlock(AS1_TComData *Ptr, word Size, word *Rcv);
**         SendBlock       - byte AS1_SendBlock(AS1_TComData *Ptr, word Size, word *Snd);
**         ClearRxBuf      - byte AS1_ClearRxBuf(void);
**         ClearTxBuf      - byte AS1_ClearTxBuf(void);
**         GetCharsInRxBuf - word AS1_GetCharsInRxBuf(void);
**         GetCharsInTxBuf - word AS1_GetCharsInTxBuf(void);
**
**     (c) Copyright UNIS, a.s. 1997-2008
**     UNIS, a.s.
**     Jundrovska 33
**     624 00 Brno
**     Czech Republic
**     http      : www.processorexpert.com
**     mail      : info@processorexpert.com
** ###################################################################*/

/* MODULE AS1. */

#include "AS1.h"
#include "Events.h"


#define OVERRUN_ERR      0x01          /* Overrun error flag bit    */
#define FRAMING_ERR      0x02          /* Framing error flag bit    */
#define PARITY_ERR       0x04          /* Parity error flag bit     */
#define CHAR_IN_RX       0x08          /* Char is in RX buffer      */
#define FULL_TX          0x10          /* Full transmit buffer      */
#define RUNINT_FROM_TX   0x20          /* Interrupt is in progress  */
#define FULL_RX          0x40          /* Full receive buffer       */
#define NOISE_ERR        0x80          /* Noise erorr flag bit      */
#define IDLE_ERR         0x0100        /* Idle character flag bit   */
#define BREAK_ERR        0x0200        /* Break detect              */
#define COMMON_ERR       0x0800        /* Common error of RX       */

static word SerFlag;                   /* Flags for serial communication */
                                       /* Bits: 0 - OverRun error */
                                       /*       1 - Framing error */
                                       /*       2 - Parity error */
                                       /*       3 - Char in RX buffer */
                                       /*       4 - Full TX buffer */
                                       /*       5 - Running int from TX */
                                       /*       6 - Full RX buffer */
                                       /*       7 - Noise error */
                                       /*       8 - Idle character  */
                                       /*       9 - Break detected  */
                                       /*      10 - Unused */
                                       /*      11 - Unused */
static word InpLen;                    /* Length of input buffer's content */
static AS1_TComData *InpPtrR;          /* Pointer for reading from input buffer */
static AS1_TComData *InpPtrW;          /* Pointer for writing to input buffer */
static AS1_TComData InpBuffer[AS1_INP_BUF_SIZE]; /* Input buffer for SCI commmunication */
static word OutLen;                    /* Length of output bufer's content */
static AS1_TComData *OutPtrR;          /* Pointer for reading from output buffer */
static AS1_TComData *OutPtrW;          /* Pointer for writing to output buffer */
static AS1_TComData OutBuffer[AS1_OUT_BUF_SIZE]; /* Output buffer for SCI commmunication */

/*
** ===================================================================
**     Method      :  HWEnDi (bean AsynchroSerial)
**
**     Description :
**         Enables or disables the peripheral(s) associated with the bean.
**         The method is called automatically as a part of the Enable and 
**         Disable methods and several internal methods.
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void HWEnDi(void)
{
  getReg(SCI_STAT);                    /* Reset interrupt request flags */
  setRegBits(SCI_CTRL1, (SCI_CTRL1_TE_MASK | SCI_CTRL1_RE_MASK | SCI_CTRL1_RFIE_MASK | SCI_CTRL1_REIE_MASK)); /* Enable device */
}

/*
** ===================================================================
**     Method      :  AS1_RecvChar (bean AsynchroSerial)
**
**     Description :
**         If any data is received, this method returns one
**         character, otherwise it returns an error code (it does
**         not wait for data). This method is enabled only if the
**         receiver property is enabled.
**         [Note:] Because the preferred method to handle error and
**         break exception in the interrupt mode is to use events
**         <OnError> and <OnBreak> the return value ERR_RXEMPTY has
**         higher priority than other error codes. As a consequence
**         the information about an exception in interrupt mode is
**         returned only if there is a valid character ready to be
**         read.
**         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. Then the
**         status of the DMA transfer can be checked using
**         GetCharsInRxBuf method. See an example of a typical usage
**         for details about the communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Chr             - Pointer to a received character
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_RXEMPTY - No data in receiver
**                           ERR_BREAK - Break character is detected
**                           (only when the <Interrupt service>
**                           property is disabled and the <Break
**                           signal> property is enabled)
**                           ERR_COMMON - common error occurred (the
**                           <GetError> method can be used for error
**                           specification)
**                           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
**                           only ERR_OK, ERR_RXEMPTY, and ERR_SPEED
**                           error code can be returned from this
**                           method.
** ===================================================================
*/
byte AS1_RecvChar(AS1_TComData *Chr)
{
  register byte Result = ERR_OK;       /* Return error code */

  if (InpLen > 0x00) {                 /* Is number of received chars greater than 0? */
    EnterCritical();                   /* Disable global interrupts */
    InpLen--;                          /* Decrease number of received chars */
    *Chr = *(InpPtrR++);               /* Received char */
    if (InpPtrR >= (InpBuffer + AS1_INP_BUF_SIZE)) { /* Is the pointer out of the receive buffer? */
      InpPtrR = InpBuffer;             /* Set pointer to the first item into the receive buffer */
    }
    Result = (byte)((SerFlag & (OVERRUN_ERR|COMMON_ERR|FULL_RX))? ERR_COMMON : ERR_OK);
    SerFlag &= ~(OVERRUN_ERR|COMMON_ERR|FULL_RX|CHAR_IN_RX); /* Clear all errors in the status variable */
    ExitCritical();                    /* Enable global interrupts */
  } else {
    return ERR_RXEMPTY;                /* Receiver is empty */
  }
  return Result;                       /* Return error code */
}

/*
** ===================================================================
**     Method      :  AS1_SendChar (bean AsynchroSerial)
**
**     Description :
**         Sends one character to the channel. If the bean is
**         temporarily disabled (Disable method) SendChar method
**         only stores data into an output buffer. In case of a zero
**         output buffer size, only one character can be stored.
**         Enabling the bean (Enable method) starts the transmission
**         of the stored data. This method is available only if the
**         transmitter property is enabled.
**         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 selected DMA channel. Then the
**         status of the DMA transfer can be checked using
**         GetCharsInTxBuf method. See an example of a typical usage
**         for details about communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**         Chr             - Character to send
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_TXFULL - Transmitter is full
** ===================================================================
*/
byte AS1_SendChar(AS1_TComData Chr)
{
  if (OutLen == AS1_OUT_BUF_SIZE) {    /* Is number of chars in buffer is the same as a size of the transmit buffer */
    return ERR_TXFULL;                 /* If yes then error */
  }
  EnterCritical();                     /* Disable global interrupts */
  OutLen++;                            /* Increase number of bytes in the transmit buffer */
  *(OutPtrW++) = Chr;                  /* Store char to buffer */
  if (OutPtrW >= (OutBuffer + AS1_OUT_BUF_SIZE)) { /* Is the pointer out of the transmit buffer */
    OutPtrW = OutBuffer;               /* Set pointer to first item in the transmit buffer */
  }
  setRegBit(SCI_CTRL1, TEIE);          /* Enable transmit interrupt */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  AS1_RecvBlock (bean AsynchroSerial)
**
**     Description :
**         If any data is received, this method returns the block of
**         the data and its length (and incidental error), otherwise
**         it returns an error code (it does not wait for data).
**         This method is available only if non-zero length of the
**         input buffer is defined and the receiver property is
**         enabled.
**         If less than requested number of characters is received
**         only the available data is copied from the receive buffer
**         to the user specified destination. The value ERR_EXEMPTY
**         is returned and the value of variable pointed by the Rcv
**         parameter is set to the number of received characters.
**         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. Then the
**         status of the DMA transfer can be checked using
**         GetCharsInRxBuf method. See an example of a typical usage
**         for details about communication using DMA.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * Ptr             - Pointer to the block of received data
**         Size            - Size of the block
**       * Rcv             - Pointer to real number of the received
**                           data
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_RXEMPTY - The receive buffer didn't
**                           contain the requested number of data.
**                           Only available data has been returned.
**                           ERR_COMMON - common error occurred (the
**                           GetError method can be used for error
**                           specification)
**                           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
**                           only ERR_OK, ERR_RXEMPTY, and ERR_SPEED
**                           error codes can be returned from this
**                           method.
** ===================================================================
*/
byte AS1_RecvBlock(AS1_TComData *Ptr,word Size,word *Rcv)
{
  register word count;                 /* Number of received chars */
  register byte result = ERR_OK;       /* Last error */

  for (count = 0x00; count < Size; count++) {
    result = AS1_RecvChar(Ptr++);
    if (result != ERR_OK) {            /* Receiving given number of chars */
      *Rcv = count;                    /* Return number of received chars */
      return result;                   /* Return last error */
    }
  }
  *Rcv = count;                        /* Return number of received chars */
  return result;                       /* OK */
}

/*
** ===================================================================
**     Method      :  AS1_SendBlock (bean AsynchroSerial)
**
**     Description :
**         Sends a block of characters to the channel.
**         This method is available only if non-zero length of the
**         output buffer is defined and the transmitter property is
**         enabled.
**         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. Then the
**         status of the DMA transfer can be checked using
**         GetCharsInTxBuf method. See 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_SPEED - This device does not work in
**                           the active speed mode
**                           ERR_TXFULL - It was not possible to send
**                           requested number of bytes
** ===================================================================
*/
byte AS1_SendBlock(AS1_TComData *Ptr,word Size,word *Snd)
{
  register word count;                 /* Number of sent chars */
  register byte result = ERR_OK;       /* Last error */

  for (count = 0x00; count < Size; count++) {
    result = AS1_SendChar(*Ptr++);
    if (result != ERR_OK) {            /* Sending given number of chars */
      *Snd = count;                    /* Return number of sent chars */
      return result;                   /* Return last error */
    }
  }
  *Snd = count;                        /* Return number of sended chars */
  return result;                       /* Return error code */
}

/*
** ===================================================================
**     Method      :  AS1_ClearRxBuf (bean AsynchroSerial)
**
**     Description :
**         Clears the receive buffer.
**         This method is available only if non-zero length of the
**         input buffer is defined and the receiver property is
**         enabled.
**         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 selected DMA channel.
**     Parameters  : None
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
** ===================================================================
*/
byte AS1_ClearRxBuf(void)
{
  EnterCritical();                     /* Disable global interrupts */
  InpLen = 0x00;                       /* Set number of chars in the transmit buffer to 0 */
  InpPtrR = InpPtrW = InpBuffer;       /* Set pointers on the first item in the transmit buffer */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  AS1_ClearTxBuf (bean AsynchroSerial)
**
**     Description :
**         Clears the transmit buffer.
**         This method is available only if non-zero length of the
**         output buffer is defined and the receiver property is
**         enabled.
**         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 selected DMA channel.
**     Parameters  : None
**     Returns     :
**         ---             - Error code, possible codes:
**                           ERR_OK - OK
**                           ERR_SPEED - This device does not work in
**                           the active speed mode
** ===================================================================
*/
byte AS1_ClearTxBuf(void)
{
  EnterCritical();                     /* Disable global interrupts */
  OutLen = 0x00;                       /* Set number of chars in the receive buffer to 0 */
  OutPtrR = OutPtrW = OutBuffer;       /* Set pointers on the first item in the receive buffer */
  ExitCritical();                      /* Enable global interrupts */
  return ERR_OK;                       /* OK */
}

/*
** ===================================================================
**     Method      :  AS1_GetCharsInRxBuf (bean AsynchroSerial)
**
**     Description :
**         Returns the number of characters in the input buffer.
**         This method is available only if the receiver property is
**         enabled.
**         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     :
**         ---             - The number of characters in the input
**                           buffer.
** ===================================================================
*/
word AS1_GetCharsInRxBuf(void)
{
  return InpLen;                       /* Return number of chars in receive buffer */
}

/*
** ===================================================================
**     Method      :  AS1_GetCharsInTxBuf (bean AsynchroSerial)
**
**     Description :
**         Returns the number of characters in the output buffer.
**         This method is available only if the transmitter property
**         is enabled.
**         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     :
**         ---             - The number of characters in the output
**                           buffer.
** ===================================================================
*/
word AS1_GetCharsInTxBuf(void)
{
  return OutLen;                       /* Return number of chars in the transmitter buffer */
}

/*
** ===================================================================
**     Method      :  AS1_InterruptRx (bean AsynchroSerial)
**
**     Description :
**         The method services the receive interrupt of the selected 
**         peripheral(s) and eventually invokes the bean's event(s).
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
#define ON_ERROR    1
#define ON_FULL_RX  2
#define ON_RX_CHAR  4
#pragma interrupt alignsp saveall
void AS1_InterruptRx(void)
{
  register AS1_TComData Data;          /* Temporary variable for data */
  register word OnFlags = 0x00;        /* Temporary variable for flags */
  register word StatReg = getReg(SCI_STAT); /* Read status register */

  if (StatReg & (SCI_STAT_OR_MASK|SCI_STAT_NF_MASK|SCI_STAT_FE_MASK|SCI_STAT_PF_MASK)) { /* Is any error flag set? */
    setReg(SCI_STAT, 0x00);            /* Reset error request flags */
    if(StatReg & (SCI_STAT_OR_MASK|SCI_STAT_NF_MASK|SCI_STAT_FE_MASK|SCI_STAT_PF_MASK)) { /* Is an error detected? */
      SerFlag |= COMMON_ERR;           /* If yes then set an internal flag */
    }
    AS1_OnError();                     /* If yes then invoke user event */
  }
  if (StatReg & SCI_STAT_RDRF_MASK) {  /* Is the receiver interrupt flag set? */
    Data = (AS1_TComData)getReg(SCI_DATA); /* Read data from the receiver */
    if (InpLen < AS1_INP_BUF_SIZE) {   /* Is number of bytes in the receive buffer lower than size of buffer? */
      InpLen++;                        /* Increse number of chars in the receive buffer */
      *(InpPtrW++) = Data;             /* Save received char to the receive buffer */
      if (InpPtrW >= (InpBuffer + AS1_INP_BUF_SIZE)) { /* Is the pointer out of the receive buffer? */
        InpPtrW = InpBuffer;           /* Set pointer on the first item into the receive buffer */
      }
      OnFlags |= ON_RX_CHAR;           /* Set flag "OnRXChar" */
      if (InpLen == AS1_INP_BUF_SIZE) { /* Is number of bytes in the receive buffer equal as a size of buffer? */
        OnFlags |= ON_FULL_RX;         /* If yes then set flag "OnFullRxBuff" */
      }
    } else {
      SerFlag |= FULL_RX;              /* If yes then set flag buffer overflow */
      OnFlags |= ON_ERROR;             /* Set flag "OnError" */
    }
    if (OnFlags & ON_ERROR) {          /* Was error flag detect? */
      AS1_OnError();                   /* If yes then invoke user event */
    }
    else {
      if (OnFlags & ON_RX_CHAR) {      /* Is OnRxChar flag set? */
        AS1_OnRxChar();                /* If yes then invoke user event */
      }
      if (OnFlags & ON_FULL_RX) {      /* Is OnFullRxBuf flag set? */
        AS1_OnFullRxBuf();             /* If yes then invoke user event */
      }
    }
  }
}

/*
** ===================================================================
**     Method      :  AS1_InterruptTx (bean AsynchroSerial)
**
**     Description :
**         The method services the receive interrupt of the selected 
**         peripheral(s) and eventually invokes the bean's event(s).
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
#define ON_FREE_TX  1
#define ON_TX_CHAR  2
#pragma interrupt alignsp saveall
void AS1_InterruptTx(void)
{
  register word OnFlags = 0x00;        /* Temporary variable for flags */

  if (SerFlag & RUNINT_FROM_TX) {      /* Is flag "running int from TX" set? */
    OnFlags |= ON_TX_CHAR;             /* Set flag "OnTxChar" */
  }
  SerFlag &= ~RUNINT_FROM_TX;          /* Reset flag "running int from TX" */
  if (OutLen) {                        /* Is number of bytes in the transmit buffer greater then 0? */
    OutLen--;                          /* Decrease number of chars in the transmit buffer */
    SerFlag |= RUNINT_FROM_TX;         /* Set flag "running int from TX"? */
    getReg(SCI_STAT);                  /* Reset interrupt request flags */
    SCI_DATA = (AS1_TComData)*(OutPtrR++); /* Store char to transmitter register */
    if (OutPtrR >= (OutBuffer + AS1_OUT_BUF_SIZE)) { /* Is the pointer out of the transmit buffer? */
      OutPtrR = OutBuffer;             /* Set pointer on the first item into the transmit buffer */
    }
  } else {
    OnFlags |= ON_FREE_TX;             /* Set flag "OnFreeTxBuf" */
    clrRegBit(SCI_CTRL1, TEIE);        /* Disable transmit interrupt */
  }
  if (OnFlags & ON_TX_CHAR) {          /* Is flag "OnTxChar" set? */
    AS1_OnTxChar();                    /* If yes then invoke user event */
  }
  if (OnFlags & ON_FREE_TX) {          /* Is flag "OnFreeTxBuf" set? */
    AS1_OnFreeTxBuf();                 /* If yes then invoke user event */
  }
}

/*
** ===================================================================
**     Method      :  AS1_Init (bean AsynchroSerial)
**
**     Description :
**         Initializes the associated peripheral(s) and the bean 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 AS1_Init(void)
{
  SerFlag = 0x00;                      /* Reset flags */
  /* SCI_CTRL1: LOOP=0,SWAI=0,RSRC=0,M=0,WAKE=0,POL=0,PE=0,PT=0,TEIE=0,TIIE=0,RFIE=0,REIE=0,TE=0,RE=0,RWU=0,SBK=0 */
  setReg(SCI_CTRL1, 0x00);             /* Set the SCI configuration */
  InpLen = 0x00;                       /* No char in the receive buffer */
  InpPtrW = InpPtrR = InpBuffer;       /* Set pointer on the first item in the receive buffer */
  OutLen = 0x00;                       /* No char in the transmit buffer */
  OutPtrW = OutPtrR = OutBuffer;       /* Set pointer on the first item in the transmit buffer */
  /* SCI_RATE: SBR=0x36,FRAC_SBR=3 */
  setReg(SCI_RATE, 0x01B3);            /* Set prescaler bits */
  HWEnDi();                            /* Enable/disable device according to status flags */
}


/* END AS1. */


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