621 lines
16 KiB
C

/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "InternalUart.h"
#include "uart.h"
#include <stdio.h>
//#include "Watchdog.h"
#include "digitalio.h"
#include "NetworkProtocol.h"
/* ************************************************************************** */
/* Local variables */
char acIntUartRxBuff[MAX_INTERNAL_UART_PORT][INTERNAL_UART_BUFFER_DEPTH]; //Rx Buffers
stInternalUartData astInternalUartData[MAX_INTERNAL_UART_PORT]; //port management data
unsigned int LoraData = 0;
void process(void);
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void InternalUartInit(void)
{
//Setup port 1
U1MODEbits.ON = 0; //disable module
U1STA = 0;
U1STAbits.UTXEN = 0; //disable transmitter
IPC6bits.U1IP = 7; //priority 7
IPC6bits.U1IS = 0; //sub-priority 3
U1STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted
// U1STAbits.UTXSEL = 0b01; // //JFM 2012-08-27
IFS0bits.U1TXIF = 0; //clear interrupt flag
IEC0bits.U1TXIE = 0; //enable tx interrupt
U1STAbits.URXISEL = 0b00; //interrupt for each character received
IFS0bits.U1RXIF = 0;
#ifdef POLL_UART1_RX
IEC0bits.U1RXIE = 0; //disable rx interrupts
#else
IEC0bits.U1RXIE = 1; //enable rx interrupts
#endif
U1STAbits.URXEN = 1; //enable receiver
U1STAbits.UTXEN = 1; //enable receiver
U1MODEbits.ON = 0; //disable module
//Setup port 2
//
U2MODEbits.ON = 0; //disable module
U2STA = 0;
U2STAbits.UTXEN = 0; //disable transmitter
IPC8bits.U2IP = 7; //priority 7
IPC8bits.U2IS = 0; //sub-priority 2
U2STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted
IFS1bits.U2TXIF = 0; //clear interrupt flag
IEC1bits.U2TXIE = 0; //enable tx interrupt
U2STAbits.URXISEL = 0b00; //interrupt for each character received
IFS1bits.U2RXIF = 0;
#ifdef POLL_UART2_RX
IEC1bits.U2RXIE = 0; //disable rx interrupts
#else
IEC1bits.U2RXIE = 1; //enable rx interrupts
#endif
U2STAbits.URXEN = 1; //enable receiver
U2STAbits.UTXEN = 1;
U2MODEbits.ON = 0; //disable module
int i;
for(i = 0; i < MAX_INTERNAL_UART_PORT; i++)
{
astInternalUartData[i].pcTxDataPtr = 0;
astInternalUartData[i].iNbFIFOPendingBytes = 0;
astInternalUartData[i].iTxDataSize = 0;
astInternalUartData[i].iTxDataCounter = 0;
astInternalUartData[i].iIsBusy = 0;
astInternalUartData[i].iIsOpened = 0;
astInternalUartData[i].iUartHandle = 0;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//int SetIntalUartInterrupts(int p_iUartPort, int p_iRxInterrupt,int p_iTxInterrupt)
//{
// if(p_iUartPort > MAX_INTERNAL_UART_PORT)
// return UART_INVALID_PORT;
//
// switch(p_iUartPort)
// {
// case INTERNAL_UART_PORT_1:
// {
// if(p_iTxInterrupt)
// {
// IFS0bits.U1TXIF = 0; //clear interrupt flag
// IEC0bits.U1TXIE = 1; //enable tx interrupt
// }
// else
// {
// IEC0bits.U1TXIE = 0; //disable tx interrupt
// U1STAbits.UTXEN = 1; //This bit must be set when working without interrupts
// }
// if(p_iRxInterrupt)
// {
// IFS0bits.U1RXIF = 0;
// IEC0bits.U1RXIE = 1; //enable rx interrupt
// }
// else
// {
// IEC0bits.U1RXIE = 0; //disable rx interrupt
// }
// break;
// }
// case INTERNAL_UART_PORT_2:
// {
// if(p_iTxInterrupt)
// {
// IFS1bits.U2TXIF = 0; //clear interrupt flag
// IEC1bits.U2TXIE = 1; //enable tx interrupt
// }
// else
// {
// IEC1bits.U2TXIE = 0; //disable tx interrupt
// U2STAbits.UTXEN = 1; //This bit must be set when working without interrupts
// }
// if(p_iRxInterrupt)
// {
// IFS1bits.U2RXIF = 0;
// IEC1bits.U2RXIE = 1; //enable rx interrupt
// }
// else
// {
// IEC1bits.U2RXIE = 0; //disable rx interrupt
// }
// break;
// }
// default:
// {
// return UART_INVALID_PORT;
// }
// }
// return UART_OK;
//}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int OpenInternalPort(int p_iUartPort,int p_iUartHandle,char *p_pcHeadPtr, char *p_pcTailPtr, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable)
{
if(p_iUartPort > MAX_INTERNAL_UART_PORT)
return UART_INVALID_PORT;
int iBRG = (PERIPHERAL_FREQ/(4*p_iBaudRate)) - 1;
int iMask = 0;
switch(p_iNbStopBits)
{
case INT_UART_ONE_STOP_BIT:
{
break;
}
case INT_UART_TWO_STOP_BITS:
{
iMask |= 0x00000001;
break;
}
}
astInternalUartData[p_iUartPort].iUartHandle = p_iUartHandle;
switch(p_iParityEnable)
{
case INT_UART_NO_PARITY:
{
break;
}
case INT_UART_EVEN_PARITY:
{
iMask |= 0x00000002;
break;
}
case INT_UART_ODD_PARITY:
{
iMask |= 0x00000004;
break;
}
}
switch(p_iUartPort)
{
case INTERNAL_UART_PORT_1:
{
INTERNAL_UART1_TX_PIN_DIR = PIN_OUTPUT;
INTERNAL_UART1_TX_PIN = 1;
U1MODE = iMask;
U1MODEbits.BRGH = 1;
U1BRG = iBRG;
U1MODEbits.ON = 1; //enable module
break;
}
case INTERNAL_UART_PORT_2:
{
INTERNAL_UART2_TX_PIN_DIR = PIN_OUTPUT;
INTERNAL_UART2_TX_PIN = 1;
U2MODE = iMask;
U2MODEbits.BRGH = 1;
U2BRG = iBRG;
U2MODEbits.ON = 1; //enable module
break;
}
}
astInternalUartData[p_iUartPort].iIsOpened = 1;
return UART_OK;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int SendInternalUartData(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort, char *p_pcSourceBufferHead, char *p_pcSourceBufferTail)
{
int iBufSize;
int iAvailableBufSize;
char *p_cDataPointer;
int i;
stInternalUartData *p_stUartDataPtr = &astInternalUartData[p_iUartPort];
if(p_stUartDataPtr->iIsOpened == 0)
return UART_PORT_NOT_OPENED;
//We use a FIFO stack that must be empty before a new transaction can occur
//if(p_stUartDataPtr->iNbFIFOPendingBytes != 0) //If FIFO not empty
if(p_stUartDataPtr->iIsBusy == 1)
return UART_PORT_BUSY; //no space is available so flag the port as BUSY...
iBufSize = p_iDataSize;
if(iBufSize > INTERNAL_UART_BUFFER_DEPTH)
iBufSize = INTERNAL_UART_BUFFER_DEPTH;
p_cDataPointer = p_stUartDataPtr->pcTxDataPtr = &p_stUartDataPtr->acIntUartTxFIFO[0];
p_stUartDataPtr->iNbFIFOPendingBytes = iBufSize;
//Fill FIFO with data;
for(i = 0; i< iBufSize; i++)
{
*p_cDataPointer++ = *p_pcDataBuf++;
if(p_pcDataBuf > p_pcSourceBufferTail) //check for wrapping of source data circular buffer.
p_pcDataBuf = p_pcSourceBufferHead;
}
p_stUartDataPtr->iIsBusy = 1; //informative flag to know we are TXing.
//Begin Transmission
//A TX interrupt will be generated immediately after setting UTXEN
switch(p_iUartPort)
{
case INTERNAL_UART_PORT_1:
{
if(IEC0bits.U1TXIE)
{
//We consider at this point that the data has been sent for the upper layer.
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
U1STAbits.UTXEN = 1;
}
else
{
int i;
for(i = 0; i < iBufSize; i++)
{
// KickWatchdog();
U1TXREG = *p_stUartDataPtr->pcTxDataPtr++;
while(U1STAbits.TRMT == 0);
}
p_stUartDataPtr->iIsBusy = 0;
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
}
break;
}
case INTERNAL_UART_PORT_2:
{
if(IEC1bits.U2TXIE)
{
//We consider at this point that the data has been sent for the upper layer.
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
U2STAbits.UTXEN = 1;
}
else
{
int i;
for(i = 0; i < iBufSize; i++)
{
// KickWatchdog();
U2TXREG = *p_stUartDataPtr->pcTxDataPtr++;
while(U2STAbits.TRMT == 0);
}
p_stUartDataPtr->iIsBusy = 0;
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
}
break;
}
}
return UART_OK;
}
int SendInternalUartDataBlocking(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort)
{
int i;
int temp = IEC1;
switch(p_iUartPort)
{
case INTERNAL_UART_PORT_1:
{
IEC0bits.U1TXIE = 0;
for(i = 0; i < p_iDataSize; i++)
{
//LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN;
U1TXREG = *p_pcDataBuf++;
while(U1STAbits.TRMT == 0);
}
//LORA_MODULE_TX_LED_PIN = LED_OFF;
IFS0bits.U1TXIF = 0;
IEC1 = temp;
break;
}
case INTERNAL_UART_PORT_2:
{
IEC1bits.U2TXIE = 0;
for(i = 0; i < p_iDataSize; i++)
{
//LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN;
U2TXREG = *p_pcDataBuf++;
while(U2STAbits.TRMT == 0);
}
// LORA_MODULE_TX_LED_PIN = LED_OFF;
IFS1bits.U2TXIF = 0;
IEC1 = temp;
break;
}
}
return UART_OK;
}
void TickInternalUart(void)
{
#ifdef POLL_UART1_RX
if(U1STAbits.URXDA == 1)
{
if(U1STAbits.OERR) //Buffer overrun error. Data is lost.
{
U1STAbits.OERR = 0;
}
int i = 0;
while(U1STAbits.URXDA && i < INTERNAL_UART_BUFFER_DEPTH)
{
char NewByte = U1RXREG;
// DriveProtocolRxData(&NewByte,1);
acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte;
}
// UartReceiveData(UART_1,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
// DriveProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
}
#endif
#ifdef POLL_UART2_RX
if(U2STAbits.URXDA == 1)
{
int i = 0;
while(U2STAbits.URXDA == 1 && i < INTERNAL_UART_BUFFER_DEPTH)
{
char NewByte = U2RXREG;
// acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte;
LORA_MODULE_RX_LED_PIN = ~LORA_MODULE_RX_LED_PIN;
ProtocolAnalyzeNewData(NewByte);
// LoraData <<= 8;
// unsigned int toto = NewByte;
// toto &= 0x000000FF;
// LoraData |= toto;
//
// if(LoraData == 0xDEADBEEF)
// {
// HEARTBEAT_LED_1_PIN = ~HEARTBEAT_LED_1_PIN;
// LORA_ACTIVITY_LED_PIN = ~LORA_ACTIVITY_LED_PIN;
// LoraData = 0;
// }
// HEARTBEAT_LED_2_PIN = ~HEARTBEAT_LED_2_PIN;
}
if(U2STAbits.OERR) //Buffer overrun error. Data is lost.
{
U2STAbits.OERR = 0;
printf("Overrun\n");
}
// UartReceiveData(UART_2,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
// CUProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
}
#endif
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void __ISR(_UART_1_VECTOR, ipl7) InternalUart1AInterrupt(void) //Internal UART 1 = port série vers le Network
{
stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1];
if(IFS0bits.U1TXIF && IEC0bits.U1TXIE)
{
IFS0bits.U1TXIF = 0;
//Check if there is still data to send in FIFO
if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
{
U1STAbits.UTXEN = 0; //all data sent, stop transmitter
p_acUartDataPtr->iIsBusy = 0;
}
else
{
do
{
U1TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data
p_acUartDataPtr->iNbFIFOPendingBytes--;
}
while((U1STAbits.UTXBF == 0) && //while there is space in buffer
(p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send
// HCAM
// if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
// {
// // U1STAbits.UTXEN = 0; //all data sent, stop transmitter
// p_acUartDataPtr->iIsBusy = 0;
// }
}
}
if(IFS0bits.U1RXIF && IEC0bits.U1RXIE)
{
char NewByte;
int i;
IFS0bits.U1RXIF = 0;
if(U1STAbits.OERR) //Buffer overrun error. Data is lost.
{
U1STAbits.OERR = 0;
IFS0bits.U1RXIF = 0;
printf("UART1 OERR\n");
return;
}
i = 0;
while(U1STAbits.URXDA)
{
NewByte = U1RXREG;
acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte;
}
UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void __ISR(_UART_2_VECTOR, ipl7) InternalUart2Interrupt(void) //UART2 = port série vers le module LoRa
{
stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2];
if(IFS1bits.U2TXIF && IEC1bits.U2TXIE)
{
IFS1bits.U2TXIF = 0;
//Check if there is still data to send in FIFO
if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
{
U2STAbits.UTXEN = 0; //all data sent, stop transmitter
p_acUartDataPtr->iIsBusy = 0;
//LORA_MODULE_TX_LED_PIN = LED_OFF;
}
else
{
do
{
U2TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data
p_acUartDataPtr->iNbFIFOPendingBytes--;
}
while((U2STAbits.UTXBF == 0) && //while there is space in buffer
(p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send
}
}
if(IFS1bits.U2RXIF && IEC1bits.U2RXIE)
{
IFS1bits.U2RXIF = 0;
char NewByte;
int i;
if(U2STAbits.OERR) //Buffer overrun error. Data is lost.
{
U2STAbits.OERR = 0;
IFS1bits.U2RXIF = 0;
printf("UART2 OERR\n");
return;
}
i = 0;
while(U2STAbits.URXDA)
{
NewByte = U2RXREG;
acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte;
}
UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Resets UART1 without closing it. Used when comm crashes.
void ResetUart1(void)
{
U1MODEbits.ON = 0; //disable module
U1STAbits.UTXEN = 0; //disable transmitter
IEC0bits.U1TXIE = 0; //disable tx interrupt
IFS0bits.U1TXIF = 0; //clear interrupt flag
IEC0bits.U1TXIE = 0; //enable tx interrupt
IEC0bits.U1RXIE = 0; //disable rx interrupts
IEC0bits.U1RXIE = 0; //disable rx interrupts
IFS0bits.U1RXIF = 1;
#ifdef POLL_UART1_RX
IEC0bits.U1RXIE = 0; //disable rx interrupts
#else
IEC0bits.U1RXIE = 1; //enable rx interrupts
#endif
U1STAbits.URXEN = 1; //enable receiver
astInternalUartData[INTERNAL_UART_PORT_1].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1].acIntUartTxFIFO[0];
astInternalUartData[INTERNAL_UART_PORT_1].iTxDataSize = 0;
astInternalUartData[INTERNAL_UART_PORT_1].iIsBusy = 0;
U1MODEbits.ON = 1; //enable module
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void ResetUart2(void)
{
//Setup port 2
//
U2MODEbits.ON = 0; //disable module
U2STAbits.UTXEN = 0; //disable transmitter
IEC1bits.U2TXIE = 0; //disable tx interrupt
IFS1bits.U2TXIF = 0; //clear interrupt flag
IEC1bits.U2TXIE = 0; //enable tx interrupt
IEC1bits.U2RXIE = 0; //disable rx interrupts
IFS1bits.U2RXIF = 1;
#ifdef POLL_UART2_RX
IEC1bits.U2RXIE = 0; //disable rx interrupts
#else
IEC1bits.U2RXIE = 1; //enable rx interrupts
#endif
U2STAbits.URXEN = 1; //enable receiver
astInternalUartData[INTERNAL_UART_PORT_2].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2].acIntUartTxFIFO[0];
astInternalUartData[INTERNAL_UART_PORT_2].iTxDataSize = 0;
astInternalUartData[INTERNAL_UART_PORT_2].iIsBusy = 0;
U2MODEbits.ON = 1; //disable module
}
//-----------------------------------------------------------------------------
void process(void)
{
}
//EOF