/****************************************************************************/
/* Copyright 2016 MBARI.                                                    */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/

#include <xc.h>
#include <string.h>
#include <stdio.h>
#include "HardwareProfile.h"
#include "uart1.h"
#include "timer.h"


extern unsigned short AlarmCnt;//Global incremented in AlarmISR


/*---------------------------------------------------------------------
  Function name: vInitU1/U2
  Description: Initialization of UART1/2 module
  Input parameters: -
  Output parameters: -
-----------------------------------------------------------------------*/
void vInitU1 ( void )
{
	U1MODE = 0; // Clear UART1 mode register
	U1STA = 0;	// Clear UART1 status register

	U1BRG = (FCY/(16*BAUD_RATE_UART1))-1; // Calculate value of baud rate register
    
	U1MODEbits.UARTEN = 1;   // Enable UART1 module
	U1STAbits.UTXEN = 1;     // Enable UART1 transmit 
    
    ANSB = 0xFFF8; //make RB2/U1RX digital input buffer (not analog)
}

void vInitU2 ( void )
{
	U2MODE = 0; // Clear UART2 mode register
	U2STA = 0;	// Clear UART2 status register

	U2BRG = (FCY/(16*BAUD_RATE_UART2))-1; // Calculate value of baud rate register
    
    IPC7bits.U2RXIP2 = 1; //Set Uart RX Interrupt Priority
    IPC7bits.U2RXIP1 = 0;
    IPC7bits.U2RXIP0 = 0;
    
    
	U2MODEbits.UARTEN = 1;   // Enable UART2 module
	U2STAbits.UTXEN = 1;     // Enable UART2 transmit
    IEC1bits.U2RXIE = 1;     // Enable Receive Interrupt
    
    ANSB = 0xFFF8; //make RB2/U1RX digital input buffer (not analog)
    
    ClearRxFifo();
    //RxPutPt=RxGetPt=&RxFifo[0];   //RxFifo is Empty when PutPt=GetPt
}
//---------------------------------------------------------------------
void ClearRxFifo (void)
{
    int i=0;
    
    for (i=0;i<RxFifoSz;i++)RxFifo[i]=0x00;
    RxPutPt=RxGetPt=&RxFifo[0];   //RxFifo is Empty when PutPt=GetPt
    return;
}
/*---------------------------------------------------------------------
  Function name: vPutCharU
  Description: Sends one character to UART (use of blocking wait)
  Input parameters: Character to send, UART to send to
  Output parameters: -
-----------------------------------------------------------------------*/
void vPutCharU ( unsigned short cChar, int chan )
{
	if (chan ==1)
    {
        while (U1STAbits.UTXBF); // Waits when the output buffer is full
        U1TXREG = cChar;         // Puts the character to the buffer
    }
    
    if (chan ==2)
     {
        while (U2STAbits.UTXBF); // Waits when the output buffer is full
        U2TXREG = cChar;         // Puts the character to the buffer
    }       
}

/*---------------------------------------------------------------------
  Function name: vPutStrU
  Description: Sends string to UART
  Input parameters: String to send, UART to send to
  Output parameters: -
-----------------------------------------------------------------------*/
void vPutStrU ( char* pcStr, int chan )
{
    unsigned short i=0;
	while( *pcStr != 0 )
	{
        i=0;
		vPutCharU(*pcStr++,chan);
        //while(i<0x1000){i++;};
	}
}

/*---------------------------------------------------------------------
  Function name: cGetCharU
  Description: Receives character from UART1 (non-blocking)
  Input parameters: UART to read from
  Output parameters: Received character
-----------------------------------------------------------------------*/
CHAR cGetCharU( int chan )
{
    if(chan==1)
    {
        if ( U1STAbits.URXDA )    
        {return U1RXREG;}
        else
        {return(0);
        }
    }
    if(chan==2)
    {
        if ( U2STAbits.URXDA )    
        {return U2RXREG;}
        else
        {return(0);
        }
    }
    return(0);
}

int RxStr(int maxchar,char *buf,int ms_to1,int ms_bet) //read RxD1 to LF
 {
  //Read up to maxchars or until LF is read from Rx port into 
  //buf or until ms_bet millisecs elapse
  //between characters. ms_to1 = timeout to reception of 1st char. 
  //Returns number of chars read
  //A NULL is appended but not included in the character count so adjust
  //maxchar accordingly to avoid buffer overrun.
  
  char *ptr;

  AlarmCnt = 0; //reset alarm
    
  while( AlarmCnt<ms_to1  && !U1STAbits.URXDA){}; //wait for first char
  
  if(!U1STAbits.URXDA)return(0); //bail if didnt get anything
  
  for (ptr=buf;ptr<buf+maxchar;ptr++)
   {
      AlarmCnt=0; //reset
      while ( !U1STAbits.URXDA) //Wait for a char
      {
        if ( AlarmCnt >=ms_bet )  //count times the 1 ms alarm has gone off
         {*ptr='\0';//append a NULL but don't count it
           return (ptr-buf) ; //quit if a timeout
         }
       }
     
    if ( (*ptr=(char)cGetCharU(1)) == 0x0d )  //store the waiting character
      {//read an LF
       ptr++;//count the LF 
       break; //quit when LF is read
      }
   }
  *ptr='\0';//append a NULL but don't count it
  return (ptr-buf);
 } // end RxStr
//*******************************************************************************
int RxStr2(int maxchar,char *buf,int ms_to1,int ms_bet) //read RxD2 to LF or ;
 {
  //Read up to maxchars, until LF, or ; is read from Rx port into 
  //buf or until ms_bet millisecs elapse
  //between characters. ms_to1 = timeout to reception of 1st char. 
  //Returns number of chars read
  //A NULL is appended but not included in the character count so adjust
  //maxchar accordingly to avoid buffer overrun.
  
  char *ptr;

  AlarmCnt = 0; //reset alarm  
  //printf("AlarmCnt = %d,U2STAbits.OERR=%d, U2STAbits.URXDA = %d\r\n",AlarmCnt,U2STAbits.OERR,U2STAbits.URXDA);
  while( AlarmCnt<ms_to1  && !U2STAbits.URXDA){}; //wait for first char
  //printf("AlarmCnt = %d, U2STAbits.URXDA = %d\r\n",AlarmCnt,U2STAbits.URXDA);
  if(!U2STAbits.URXDA)return(0); //bail if didnt get anything
  
  for (ptr=buf;ptr<buf+maxchar;ptr++)
   {
      AlarmCnt=0; //reset
      while ( !U2STAbits.URXDA) //Wait for a char
      {
        if ( AlarmCnt >=ms_bet )  //count times the 1 ms alarm has gone off
         {*ptr='\0';//append a NULL but don't count it
           return (ptr-buf) ; //quit if a timeout
         }
       }
    *ptr=(char)cGetCharU(2);  //store the waiting character
    //LATAbits.LATA0 ^= 1;
    
    if (  (*ptr == 0x0a) || (*ptr == 0x3b) ) 
      {//read an LF or semicolon
       ptr++;//count the LF 
       break; //quit when LF is read
      }
   }
  *ptr='\0';//append a NULL but don't count it
  return (ptr-buf);
 } // end RxStr
//******************************************************************************
int UI_parse (int ms)
{
    int i=-1;
    int j=0;
    int lf=-1;
    int found=0;
    char tmp[8];
    AlarmCnt = 0; //reset alarm
    
    while( !found && (AlarmCnt < ms) ) //wait for ;
    {
        for (i=0;i<RxFifoSz;i++)
        {
            if (RxFifo[i]==0x0d){lf=i;}
            if (RxFifo[i]==0x3b){found=i;}
        }   
    }
    
    if(found)
    {
       for (i=lf;i<found;i++)
       {
           tmp[j]=RxFifo[i];
           j++;
       }
       sscanf(tmp,"%d",&i);
    }
    
    
return(i); 
}
/******************************************************************************
 *              UART2 receive ISR
 ***************************************************************/
void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void) {
    unsigned char ch;
    
    
    
    while (!U2STAbits.URXDA) {}
       
    //printf("*");
        ch=cGetCharU(2);   //Put data into fifo
        //TSerPutByte(0, (int)ch);
        *(RxPutPt++)=ch;
        if (RxPutPt==&RxFifo[RxFifoSz])  // need to wrap Put pointer?
          RxPutPt = &RxFifo[0];
        if (RxPutPt == RxGetPt )
         {//collision of Put and Get pointers
          //Newest char writes over the oldest character in Ring
          RxGetPt++;//bump Get pointer to stay ahead of Put pointer
          if(RxGetPt==&RxFifo[RxFifoSz]) RxGetPt=&RxFifo[0];//keep it legal
         } 
  
  
    IFS1bits.U2RXIF = 0;
    return;
}

/***************************************************************/