/*******************************************************************************
* NXP Semiconductors
* ALL RIGHTS RESERVED.
********************************************************************************
Services performed by NXP in this matter are performed AS IS and without 
any warranty. CUSTOMER retains the final decision relative to the total design 
and functionality of the end product. NXP neither guarantees nor will be 
held liable by CUSTOMER for the success of this project.
NXP DISCLAIMS ALL WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY INCLUDING, 
BUT NOT LIMITED TO, IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR 
A PARTICULAR PURPOSE ON ANY HARDWARE, SOFTWARE OR ADVISE SUPPLIED TO THE PROJECT
BY NXP, AND OR NAY PRODUCT RESULTING FROM NXP SERVICES. IN NO EVENT
SHALL NXP BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THIS AGREEMENT.

CUSTOMER agrees to hold NXP harmless against any and all claims demands or
actions by anyone on account of any damage, or injury, whether commercial, 
contractual, or tortuous, rising directly or indirectly as a result of an advise
or assistance supplied CUSTOMER in connection with product, services or goods 
supplied under this Agreement.
********************************************************************************
* File      main.c
* Owner     NXA19261
* Version   1.0
* Date      Aug-17-2017
* Classification   General Business Information
* Brief     SCI routines
********************************************************************************
* Detailed Description:
* SCI routines
* 
********************************************************************************
Revision History:
Version  Date         Author    Description of Changes
1.0      Aug-17-2017  NXA19261  Initial version
*******************************************************************************/
#include <string.h>
#include "SCI.h"
#include "Srec.h"
#include "derivative.h" /* include peripheral declarations */
#include "Config.h"

unsigned char RxBuff[RxBufSize];  //receive queue
unsigned char TxBuff[TxBufSize];  //transmit queue
unsigned char RxIn;               //next available location in the Rx queue
unsigned char RxOut;              //next character to be removed from the Rx queue
unsigned char TxIn;               //next available location in the Tx queue
unsigned char TxOut;              //next character to be sent from the Tx queue
volatile unsigned char RxBAvail;  //number of bytes left in the Rx queue
volatile unsigned char TxBAvail;  //number of bytes left in the Tx queue

unsigned char XOffSent;
  //flag indicating that an XOff character was sent (== 1, XOff was sent)
  
unsigned char XOffRcvd;
  //flag indicating that an XOff character was received (== 1, XOff was received)
  
unsigned char SendXOff;
  //flag indicating that the TxISR should send an XOff the next time it's called
  
unsigned char SendXOn;

/*******************************************************************************
 Function Name : InitDCI
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : NONE
 Notes         : Initialise SCI.
 Issues        : NONE
 *******************************************************************************/
void InitSCI(void)
{
  SCICR2 = 0x00;            //reset the SCI if it was previously enabled 
  RxIn = RxOut = TxIn = TxOut = 0;  //set the Rx & Tx queue indexes to zero
  RxBAvail = RxBufSize;     //the receive buffer is empty
  TxBAvail = TxBufSize;     //the transmit buffer is empty
  XOffSent = 0;             //XOff character has not been sent
  XOffRcvd = 0;             //XOff character has not been received
  SendXOff = 0;             //Don't send an XOff
  SCIBD = DEFAULT_BAUDRATE; //Initialise the Baud register
  //enable both the transmitter & receiver
  SCICR2 = SCICR2_TE_MASK + SCICR2_RE_MASK + SCICR2_RIE_MASK;
}

/*******************************************************************************
 Function Name : OutStr
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : Pointer to String 
 Modifies      : NONE
 Returns       : NONE
 Notes         : Transfer string per character.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
void OutStr(char * Str)
{
  //output 1 character at a time until we reach the end of the string
  while (*Str != 0)
    putchar(*Str++);
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : putchar
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : character 
 Modifies      : NONE
 Returns       : character we sent
 Notes         : Transfer character.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
signed char putchar(char c)
{
  while (TxBAvail == 0){};     //if there's no room in the xmit queue wait here
  
  DisableInterrupts;
  TxBuff[TxIn++] = (unsigned char)c; //put the char in the buffer, inc buffer index
  if (TxIn == TxBufSize)     //buffer index go past the end of the buffer?
    TxIn = 0;                 //yes. wrap around to the start
  TxBAvail--;                //one less character available in the buffer
  if (XOffRcvd == 0)         //if an XOff has not been received...
    SCICR2 |= SCICR2_TIE_MASK;//enable SCI transmit interrupts
  EnableInterrupts;
  
  return(c);                 //return the character we sent
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : getchar
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : character retrieved from receive buffer
 Notes         : receive character.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
signed char getchar(void)
{
  unsigned char c;                   //holds the character we'll return
  
  //if there's no characters in the Rx buffer wait here
  while (RxBAvail == RxBufSize){};
 
  DisableInterrupts;
  
  //get a character from the Rx buffer & advance the Rx index
  c = RxBuff[RxOut++];
  if (RxOut == RxBufSize)    //index go past the physical end of the buffer?
   RxOut = 0;                //yes wrap around to the start
  RxBAvail++;                //1 more byte available in the receive buffer
  
  //if an XOff was previously sent & the Rx buffer
  //has more than XOnCount bytes available
  if ((XOffSent != 0) & (RxBAvail >= XOnCount))
  {
    SendXOn = 1;
    SCICR2 |= SCICR2_TIE_MASK; //enable SCI transmit interrupts
  }
  EnableInterrupts;
  
  return(c);     //return the character retrieved from receive buffer
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : SetBaud
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : NONE
 Notes         : change baud rate.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
void SetBaud(void)
{
  signed char c;
  
  OutStr("\r\n1.) 9600\r\n"); //display baud rate selection menu
  OutStr("2.) 38400\r\n");
  OutStr("3.) 57600\r\n");
  OutStr("4.) 115200\r\n");
  OutStr("? ");
  c = getchar();              //get choice
  (void)putchar(c);           //echo choice
  
  //display message at old baudrate
  OutStr("\r\nChange Terminal Baud Rate and Press Return");
  
  //now wait until the last character has been shifted out
  while ((SCISR1 & SCISR1_TC_MASK) == 0){};
  
  switch (c) {
  
  case '1':
    SCIBD = Baud9600;
    break;
  
  case '2':
    SCIBD = Baud38400;
    break;
  
  case '3':
    SCIBD = Baud57600;
    break;
  
  case '4':
    SCIBD = Baud115200;
    break;
  
  default:                //invalid choice returns to main menu
    break;
  
  }
  
  (void)getchar();        //and wait for the user to change the baud rate
  
  OutStr("\r\n");
  OutStr("Passed\r\n");
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : RxISR
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : NONE
 Notes         : Handle received data.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
void RxISR(void)
{
  unsigned char c;
  
  c = SCIDRL;
  
  if (c == XOff)                //host want us to stop sending data?
  {
    SCICR2 &= ~SCICR2_TIE_MASK; //yes. disable transmit interrupts
    XOffRcvd = 1; //let putchar know that it may continue to place characters
                  //in the buffer but not enable Xmit interrupts
    return;
  }
  else if (c == XOn)            //host want us to start sending data?
  {
    if (TxBAvail != TxBufSize)  //anything left in the Tx buffer?
    SCICR2 |= SCICR2_TIE_MASK;  //yes. enable transmit interrupts
    XOffRcvd = 0;
    return;
  }
  
  //if the number of bytes available in the Rx buff
  //is < XOffCount & an XOff hasn't been sent
  if ((RxBAvail <= XOffCount) && (XOffSent == 0))
  {
    SendXOff = 1; //set flag to send an XOff, stopping the host from sending data
    XOffSent = 1; //set the flag showing that we've queued up to send an XOff
    
    //enable transmit interrupts,
    //so the TxISR will be called next time the TDRE bit is set
    SCICR2 |= SCICR2_TIE_MASK;
  }
  
  if (RxBAvail != 0)            //if there are bytes available in the Rx buffer
  {
    RxBAvail--;                 //reduce the count by 1
    RxBuff[RxIn++] = c;         //place the received byte in the buffer
    if (RxIn == RxBufSize)      //reached the physical end of the buffer?
    RxIn = 0;                   //yes. wrap around to the start
  }
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : TxISR
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : NONE
 Notes         : Handle transmit data.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
void TxISR(void)
{
  if (SendXOn != 0)             //request to send an XOn to the host?
  {
    SendXOn = 0;
    XOffSent = 0;               //reset the XOff flag
    SCIDRL = XOn;               //send the character
    if (TxBAvail == TxBufSize)  //anything in the Tx buffer?
    SCICR2 &= ~SCICR2_TIE_MASK; //no. disable transmit interrupts
  }
  else if (SendXOff != 0)       //request to send an XOff to the host?
  {
    SendXOff = 0;               //yes, clear the request
    SCIDRL = XOff;              //send the character
    if (TxBAvail == TxBufSize)  //anything in the Tx buffer?
    SCICR2 &= ~SCICR2_TIE_MASK; //no. disable transmit interrupts
  }
  else
  {
    SCIDRL = TxBuff[TxOut++];   //remove a character from the buffer & send it
    
    if (TxOut == TxBufSize)     //reached the physical end of the buffer?
      TxOut = 0;                //yes. wrap around to the start
      
    if (++TxBAvail == TxBufSize)  //anything left in the Tx buffer?
      SCICR2 &= ~SCICR2_TIE_MASK; //no. disable transmit interrupts
   }
}
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

/*******************************************************************************
 Function Name : SCIISR
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE 
 Modifies      : NONE
 Returns       : NONE
 Notes         : SCI interrupt routine.
 Issues        : NONE
 *******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT_RAM
#endif /* BOOTLODER_REWRITABLE */
#if SCI_MODULE == SCI0
interrupt VectorNumber_Vsci0 void SCIISR(void)
#endif /* SCI_MODULE == SCI0 */
#if SCI_MODULE == SCI1
interrupt VectorNumber_Vsci1 void SCIISR(void)
#endif /* SCI_MODULE == SCI1 */
{
  // if the RDRF OR the OR flag is set
  if (SCISR1 & (SCISR1_RDRF_MASK + SCISR1_OR_MASK))
    RxISR();              //go get a character & place it in the buffer
    
  //if transmit interrupts are enable AND the TDRE flag is set
  if ((SCICR2 & SCICR2_TIE_MASK) && (SCISR1 & SCISR1_TDRE_MASK))
    TxISR();              //go send a character to the host
}
/******************************************************************************/
#if BOOTLODER_REWRITABLE 
#pragma CODE_SEG DEFAULT
#endif /* BOOTLODER_REWRITABLE */

