#include "drvUART.h"


//********************************************************************************
//  STEP
//  Allocate two buffers for DMA transfers
//********************************************************************************/
unsigned char BufferTxA[Tx_SIZE] __attribute__((space(dma)));
//unsigned char BufferTxB[Tx_SIZE] __attribute__((space(dma)));
//volatile unsigned int BufferCount = 0; 
//volatile unsigned char FullFlagTxBuf=0;

void InitUART1()
{
	U1MODEbits.UARTEN=0;             // desactive l'UART1  
	
	U1MODEbits.USIDL = 0;	// Bit13 Continue in Idle
	U1MODEbits.IREN = 0;	// Bit12 No IR translation
	U1MODEbits.RTSMD = 0;	// Bit11 Simplex Mode
	U1MODEbits.UEN = 0;		// Bits8,9 TX,RX enabled, CTS,RTS not
	U1MODEbits.WAKE = 0;	// Bit7 No Wake up (since we don't sleep here)
	U1MODEbits.LPBACK = 0;	// Bit6 No Loop Back
	U1MODEbits.ABAUD = 0;	// Bit5 No Autobaud (would require sending '55')
	U1MODEbits.URXINV = 0;	// Bit4 IdleState = 1  (for dsPIC)
	U1MODEbits.BRGH = 0;	// Bit3 16 clocks per bit period
	U1MODEbits.PDSEL = 0;	// Bits1,2 8bit, No Parity
	U1MODEbits.STSEL = 0;	// Bit0 One Stop Bit


	U1BRG = BRGVAL;

	IPC2bits.U1RXIP = 4;	        // Mid Range Interrupt Priority level, no urgent reason
	IEC0bits.U1RXIE = 0;	        // Disable Recieve Interrupts : Validation IT RX
	
	_U1TXIF = 0;	// Clear the Transmit Interrupt Flag
	_U1TXIE = 0;	// Disable Transmit Interrupts
	_U1RXIF = 0;	// Clear the Recieve Interrupt Flag
	_U1RXIE = 0;	// Disable Recieve Interrupts

	U1MODEbits.UARTEN = 1;          //Active l'uart1
	U1STAbits.UTXEN=1;              //Active la transmision
 	Delay_Us(110); // tempo d'au moins 1 bit avant 1er envoi

}

void InitUART1_TxDMA0()
{   cfgDma0UartTx();
	
	U1MODEbits.UARTEN=0;             // desactive l'UART1  
	
	U1MODEbits.USIDL = 0;	// Bit13 Continue in Idle
	U1MODEbits.IREN = 0;	// Bit12 No IR translation
	U1MODEbits.RTSMD = 0;	// Bit11 Simplex Mode
	U1MODEbits.UEN = 0;		// Bits8,9 TX,RX enabled, CTS,RTS not
	U1MODEbits.WAKE = 0;	// Bit7 No Wake up (since we don't sleep here)
	U1MODEbits.LPBACK = 0;	// Bit6 No Loop Back
	U1MODEbits.ABAUD = 0;	// Bit5 No Autobaud (would require sending '55')
	U1MODEbits.URXINV = 0;	// Bit4 IdleState = 1  (for dsPIC)
	U1MODEbits.BRGH = 0;	// Bit3 16 clocks per bit period
	U1MODEbits.PDSEL = 0;	// Bits1,2 8bit, No Parity
	U1MODEbits.STSEL = 0;	// Bit0 One Stop Bit

	U1STAbits.UTXISEL0 = 0;			// Interrupt after one Tx character is transmitted
	U1STAbits.UTXISEL1 = 0;			                            
	U1STAbits.URXISEL  = 0;			// Interrupt after one RX character is received
	
	U1BRG = BRGVAL;

	IPC2bits.U1RXIP = 4;	        // Mid Range Interrupt Priority level, no urgent reason
	IEC0bits.U1RXIE = 0;	        // Disable Recieve Interrupts : Validation IT RX
	
	_U1TXIF = 0;	// Clear the Transmit Interrupt Flag
	_U1TXIE = 0;	// Disable Transmit Interrupts
	_U1RXIF = 0;	// Clear the Recieve Interrupt Flag
	_U1RXIE = 0;	// Disable Recieve Interrupts

	U1MODEbits.UARTEN = 1;          //Active l'uart1
	U1STAbits.UTXEN=1;              //Active la transmision
 	Delay_Us(110); // tempo d'au moins 1 bit avant 1er envoi

	
}	

void UART_puts(char * BUFF)
{
	unsigned int i=0;
	while (BUFF[i]!='\0') // tant que fin tableau non atteinte
	{
		while(U1STAbits.UTXBF); //attend buffer vide
		U1TXREG = BUFF[i]; // envoi sur TX
		i++;
	}
}

void UART_DMAputs(char * BUFF)
{
	unsigned int i=0;
	while (BUFF[i]!='\0') // tant que fin tableau non atteinte
	{
		BufferTxA[i]= BUFF[i]; // fill DMA RAM
		i++;
	}
	DMA0CNT = i-1;
	DMA0CONbits.CHEN = 1;// Enable DMA0 Channel
	DMA0REQbits.FORCE = 1;			// Manual mode: Kick-start transfert
}


// DMA0 configuration
void cfgDma0UartTx(void)
{
	//********************************************************************************
	//  STEP 3:
	//  Associate DMA Channel 0 with UART Tx
	//********************************************************************************/
	DMA0REQ = 0x000C;					// Select UART1 Transmitter
	DMA0PAD = (volatile unsigned int) &U1TXREG;
	
	//********************************************************************************
	//  STEP 5:
	//  Configure DMA Channel 0 to:
	//  Transfer data from RAM to UART
	//  One-Shot mode
	//  Register Indirect with Post-Increment
	//  Using single buffer
	//  8 transfers per buffer
	//  Transfer words
	//********************************************************************************/
	//// One-Shot, Post-Increment, RAM-to-Peripheral
	DMA0CONbits.AMODE = 0b00;
	DMA0CONbits.MODE  = 0b01;
	DMA0CONbits.DIR   = 1;
	DMA0CONbits.SIZE  = 1;
		
	DMA0CONbits.CHEN = 1;// Enable DMA0 Channel
	//********************************************************************************
	//  STEP 6:
	// Associate one buffer with Channel 0 for one-shot operation
	//********************************************************************************/
	DMA0STA = __builtin_dmaoffset(BufferTxA);
//	DMA0STB = __builtin_dmaoffset(BufferTxB);

	//********************************************************************************
	//  STEP 8:
	//	Enable DMA Interrupts
	//********************************************************************************/
	_DMA0IP = 3;
	IFS0bits.DMA0IF  = 0;			// Clear DMA Interrupt Flag
	IEC0bits.DMA0IE  = 1;			// Enable DMA interrupt

}



// when DMA Tx is finished switch buffer Tx
void __attribute__((__interrupt__)) _DMA0Interrupt(void)
{

//FullFlagTxBuf--;
DMA0CONbits.CHEN =0;
IFS0bits.DMA0IF = 0;// Clear the DMA1 Interrupt Flag
}



int write(int handle, void *buffer, unsigned int len)
{
unsigned int i = 0;   
static  int totalLenght=0;
unsigned char* c = (unsigned char*)buffer; 
unsigned char *DMA0buffer;
char test;
switch (handle) 
  { 
      case 0:       // handle 0 corresponds to stdout 
      case 1:      // handle 1 corresponds to stdin 
      case 2:        // handle 2 corresponds to stderr 
      default:  
      		while (	DMA0REQbits.FORCE = 1);  //waiting for DMA release
			DMA0buffer=	BufferTxA;	
			while((i<len) && (i<Tx_SIZE))
				{  
				
				test=c[i];	

				DMA0buffer[totalLenght] = test;
				i++;
				totalLenght++;
				}
			test=c[i-1];	
			if (test==0x0A) //||(c[i+1]==0x00))
			{	
				DMA0CNT = totalLenght-1;
				totalLenght=0;
				DMA0CONbits.CHEN  = 1;
				DMA0REQbits.FORCE = 1;			// Manual mode: Kick-start transfert
			}	
	
		

}
return(len);
}
	

