/******************************************************************************* * * * 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 "Uart.h" #include "Internaluart.h" #include #include //#include "Watchdog.h" #ifndef NO_EXTERNAL_UART #include "sc16IS740Driver.h" #endif #include "digitalio.h" //#include "DriveProtocol.h" #include "terminal.h" #include "SIM7080GInterface.h" /* ************************************************************************** */ /* Local variables */ stUartData astUartData[MAX_UART_HANDLE]; const char *gUartStrings[MAX_UART_HANDLE] = { "LORA" //UART_1 ,"LTE", //UART_5 // ,"CONSOLE" //UART_3 }; /* ************************************************************************** */ /* Private function prototypes */ //void _mon_putc(char c); //override from stdio to redirect stdout on uart 3B //void _mon_write (const char * s, unsigned int count); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void InitUart(void) { int i; InternalUartInit(); //InitSC16S740(); memset(&astUartData,0,sizeof(astUartData)); for(i = 0; i < MAX_UART_HANDLE; i++) { astUartData[i].iDataPending = 0; //This flag is 0 when : TxPtr == RxPtr OR Uart is transmitting. astUartData[i].pcTxInPtr = &astUartData[i].acTxCircularBuffer[0]; astUartData[i].pcTxOutPtr = &astUartData[i].acTxCircularBuffer[0]; //memset(&astUartData[i].acTxCircularBuffer[0],0xDE,UART_MAX_TX_BUFF_SIZE); astUartData[i].pcRxInDataPtr = astUartData[i].pcRxOutDataPtr = &astUartData[i].acRxCircularBuffer[0]; astUartData[i].iNbRxFIFOPendingBytes = 0; } //This is a physical mapping of the UARTS. //DO NOT CHANGE assignments unless hardware changed ! // astUartData[UART_1].iIsInternal = 1; astUartData[UART_1].iPhysicalUartPort = INTERNAL_UART_PORT_2; // (232) astUartData[UART_2].iIsInternal = 1; astUartData[UART_2].iPhysicalUartPort = INTERNAL_UART_PORT_5; // (232) #ifndef NO_EXTERNAL_UART astUartData[UART_3].iIsInternal = 0; astUartData[UART_3].iPhysicalUartPort = EXT_UART_1; // (SPI - 232 daughter board) #endif setbuf(stdout,NULL); //to use printf without \r fflush(stdout); UartOpenComPort(NETWORK_UART_PORT,9600,UART_ONE_STOP_BIT,UART_NO_PARITY); //Open LoRa module port UartOpenComPort(LTE_IF_UART_PORT,115200,UART_ONE_STOP_BIT,UART_NO_PARITY); //Open LTE module port #ifdef USE_PRINTF //UartOpenComPort(CONSOLE_UART_PORT,115200,UART_ONE_STOP_BIT,UART_NO_PARITY); //Open console port #endif } //----------------------------------------------------------------------------- int UartResetPort(int p_iUartHandle) { if(p_iUartHandle > MAX_UART_HANDLE) return 0; //reset the port data structures... astUartData[p_iUartHandle].iDataPending = 0; //This flag is 0 when : TxPtr == RxPtr OR Uart is transmitting. astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; astUartData[p_iUartHandle].pcRxInDataPtr = astUartData[p_iUartHandle].pcRxOutDataPtr = &astUartData[p_iUartHandle].acRxCircularBuffer[0]; astUartData[p_iUartHandle].iNbRxFIFOPendingBytes = 0; if(astUartData[UART_1].iIsInternal == 1) { switch(astUartData[p_iUartHandle].iPhysicalUartPort) { case INTERNAL_UART_PORT_1: { ResetUart1(); break; } case INTERNAL_UART_PORT_2: { ResetUart2(); break; } case INTERNAL_UART_PORT_5: { ResetUart5(); break; } default: break; } } else { #ifndef NO_EXTERNAL_UART switch(astUartData[p_iUartHandle].iPhysicalUartPort) { case EXT_UART_1: { break; } default: break; } #endif } return 1; } //----------------------------------------------------------------------------- int UartOpenComPort(int p_iUartHandle, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable) { int iStopbits,iParity,iRet; if(p_iUartHandle >= MAX_UART_HANDLE || p_iUartHandle < 0) return UART_INVALID_HANDLE; if(astUartData[p_iUartHandle].iIsInternal == 1) { switch(p_iNbStopBits) { case UART_ONE_STOP_BIT: case UART_ONE_HALF_STOP_BIT: //1˝ stop bits doesn't exist for internal uart { iStopbits = INT_UART_ONE_STOP_BIT; break; } case UART_TWO_STOP_BITS: { iStopbits = INT_UART_TWO_STOP_BITS; break; } } switch(p_iParityEnable) { case UART_NO_PARITY: { iParity = INT_UART_NO_PARITY; break; } case UART_EVEN_PARITY: { iParity = INT_UART_EVEN_PARITY; break; } case UART_ODD_PARTIY: { iParity = INT_UART_ODD_PARITY; break; } } iRet = OpenInternalPort(astUartData[p_iUartHandle].iPhysicalUartPort, p_iUartHandle, &astUartData[p_iUartHandle].acTxCircularBuffer[0], &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1], p_iBaudRate, iStopbits, iParity); } #ifndef NO_EXTERNAL_UART else { switch(p_iNbStopBits) { case UART_ONE_STOP_BIT: { iStopbits = ONE_STOP_BIT; break; } case UART_ONE_HALF_STOP_BIT: //1˝ stop bits doesn't exist for internal uart { iStopbits = ONE_HALF_STOP_BIT; break; } case UART_TWO_STOP_BITS: { iStopbits = TWO_STOP_BITS; break; } } switch(p_iParityEnable) { case UART_NO_PARITY: { iParity = NO_PARITY; break; } case UART_EVEN_PARITY: { iParity = EVEN_PARITY; break; } case UART_ODD_PARTIY: { iParity = ODD_PARITY; break; } } iRet = OpenExternalPort(astUartData[p_iUartHandle].iPhysicalUartPort, p_iUartHandle, &astUartData[p_iUartHandle].acTxCircularBuffer[0], &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1], p_iBaudRate, iStopbits, iParity); } #endif return iRet; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //All the uart callback function assignment must be done here !!! //This must be changed if hardware changes or if port assignment is changed !!! // int UartReceiveData(int p_iUartHandle, char *p_pcBuffer, int p_iSize) { int i; stUartData *p_stUartDatPtr = &astUartData[p_iUartHandle]; if(p_iUartHandle < 0 && p_iUartHandle >= MAX_UART_HANDLE) { //TODO: Flag a logic error ! return 0; } for(i = 0; i < p_iSize; i++) { *p_stUartDatPtr->pcRxInDataPtr++ = *p_pcBuffer++; if(p_stUartDatPtr->pcRxInDataPtr > &p_stUartDatPtr->acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1]) { p_stUartDatPtr->pcRxInDataPtr = &p_stUartDatPtr->acRxCircularBuffer[0]; //wrap pointer // printf("Wrap\n"); } } p_stUartDatPtr->iNbRxFIFOPendingBytes += p_iSize; if(p_stUartDatPtr->iNbRxFIFOPendingBytes >= UART_MAX_RX_BUFF_SIZE) PRINTF("RX FIFO Overflow\n"); /* switch(p_iUartHandle) { case UART_0: { break; } case UART_1: { break; } case UART_2: { break; } case UART_3: { break; } case UART_4: { break; } case UART_5: { break; } } */ return 1; } int UartGetPendingDataSize(int iUartHandle) { stUartData *p_stUartDatPtr = &astUartData[iUartHandle]; if(p_stUartDatPtr->pcRxInDataPtr == p_stUartDatPtr->pcRxOutDataPtr) { return 0; } else if(p_stUartDatPtr->pcRxOutDataPtr < p_stUartDatPtr->pcRxInDataPtr) { return(p_stUartDatPtr->pcRxInDataPtr - p_stUartDatPtr->pcRxOutDataPtr); } else { int size = &p_stUartDatPtr->acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1] - p_stUartDatPtr->pcRxOutDataPtr; size += p_stUartDatPtr->pcRxInDataPtr - &p_stUartDatPtr->acRxCircularBuffer[0]; return size; } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- int UartTransmitData(int p_iUartHandle, char *p_pcBuffer, int p_iSize) { int iRet = 0; // Case where OutPtr < InPtr // * = Available space // //Top ---->|---------------| // | * | //OutPtr ->| | // | | // | (p_pcBuffer) | //Available size = (OutPtr - Top) + (Bottom - InPtr) // | | //InPtr -->| | // | * | // | * | //Bottom ->|---------------| // Case where OutPtr > InPtr // * = Available space // //Top ---->|---------------| // | | //InPtr -->| | // | * | // | * | //available size = OutPtr - InPtr // | * | //OutPtr ->| | // | (p_pcBuffer) | // | | //Bottom ->|---------------| //Check if data buffer fits in remaining circular buffer space if(astUartData[p_iUartHandle].pcTxOutPtr < astUartData[p_iUartHandle].pcTxInPtr) { //Calculate remaining buffer space and check if it's enough to fit requested data buffer if(p_iSize > ((astUartData[p_iUartHandle].pcTxOutPtr - &astUartData[p_iUartHandle].acTxCircularBuffer[0]) + //Outptr - Top (&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1] - astUartData[p_iUartHandle].pcTxInPtr))) //Bottom - Inptr { //Drop remaining packets, flush buffer astUartData[p_iUartHandle].iDataPending = 0; astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; return UART_BUFFER_FULL; } } else if(astUartData[p_iUartHandle].pcTxInPtr < astUartData[p_iUartHandle].pcTxOutPtr) { //Calculate remaining buffer space and check if it's enough to fit requested data buffer if(p_iSize > (astUartData[p_iUartHandle].pcTxOutPtr - astUartData[p_iUartHandle].pcTxInPtr)) { //Drop remaining packets, flush buffer astUartData[p_iUartHandle].iDataPending = 0; //Force data pending flag to flush buffer astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; return UART_BUFFER_FULL; } } else //OutPtr = InPtr { if(p_iSize > UART_MAX_TX_BUFF_SIZE - 1) //message is too big to fit in buffer !!! { //Drop remaining packets, flush buffer astUartData[p_iUartHandle].iDataPending = 0; //Force data pending flag to flush buffer astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; return UART_BUFFER_FULL; } } int i; for(i = 0; i < p_iSize; i++) { *astUartData[p_iUartHandle].pcTxInPtr++ = *p_pcBuffer++; //fill circular buffer if(astUartData[p_iUartHandle].pcTxInPtr > &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]) //check for wrapping { astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0]; } } //Now flag pending data for transmission. astUartData[p_iUartHandle].iDataPending = 1; //The data send will start on next Main loop processing return iRet; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //Some data has been entirely sent //Move output pointer // int DataSentNotification(int p_iUartHandle,int DataSize) { //Check wrapping. if(astUartData[p_iUartHandle].pcTxOutPtr + DataSize < &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE]) { astUartData[p_iUartHandle].pcTxOutPtr += DataSize; } else //Pointer must wrap { //Top ------>|---------------| // | * | //Final Pos->| | // Final Pos = Top + * // | | // | (buffer) | // DataSize = & + * // | | // & = Bottom - OutPtr //OutPtr --->| | // * = DataSize - & // | & | // FinalPos = Top + (DataSize - (Bottom - OutPtr)) // | & | //Bottom --->|---------------| // if(p_iUartHandle != PRINTF_UART_PORT) // printf("Out wrap\r"); DataSize -= (&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE] - astUartData[p_iUartHandle].pcTxOutPtr); //p_iSize - (Bottom - OutPtr) astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0] + DataSize; //Top + new p_iSize } //Check if data is pending in buffer if(astUartData[p_iUartHandle].pcTxOutPtr != astUartData[p_iUartHandle].pcTxInPtr) { astUartData[p_iUartHandle].iDataPending = 1; } else { astUartData[p_iUartHandle].iDataPending = 0; // LORA_MODULE_TX_LED_PIN = LED_OFF; } return UART_OK; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //Called by main loop. Check if any uart has data pending to be sent // int UartTick(void) { int i = 0; int iRet; int p_iSize; char aTempBuffer[UART_MAX_RX_BUFF_SIZE]; TickInternalUart(); //Send... for(i = 0; i < MAX_UART_HANDLE; i++) { if(astUartData[i].iDataPending) { char *pcTxInPtr = astUartData[i].pcTxInPtr; //Check remaining data size. if(astUartData[i].pcTxOutPtr < pcTxInPtr) { p_iSize = pcTxInPtr - astUartData[i].pcTxOutPtr; } else { p_iSize = ((&astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE] - astUartData[i].pcTxOutPtr) + (pcTxInPtr - &astUartData[i].acTxCircularBuffer[0])); } if(astUartData[i].iIsInternal) //Uart handle mapped to PIC internal uart { astUartData[i].iDataPending = 0; iRet = SendInternalUartData(astUartData[i].pcTxOutPtr, p_iSize, astUartData[i].iPhysicalUartPort, &astUartData[i].acTxCircularBuffer[0], &astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]); } #ifndef NO_EXTERNAL_UART else //mapped to external uart { astUartData[i].iDataPending = 0; iRet = SendExternalUartData(astUartData[i].iPhysicalUartPort, astUartData[i].pcTxOutPtr, p_iSize,&astUartData[i].acTxCircularBuffer[0], &astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]); } #endif //TODO: manage return values switch(iRet) { case UART_OK: { break; } case UART_PORT_BUSY: case UART_BUFFER_FULL: { astUartData[i].iDataPending = 1; break; } case UART_PORT_NOT_OPENED: { break; } } } //Receive... // int iNbPendingData = astUartData[i].iNbRxFIFOPendingBytes; //JFM 2012-09-05 int iNbPendingData = UartGetPendingDataSize(i); if(iNbPendingData > 0) { int byte; for(byte = 0; byte < iNbPendingData; byte++) { aTempBuffer[byte] = *astUartData[i].pcRxOutDataPtr++; if(astUartData[i].pcRxOutDataPtr > &astUartData[i].acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1]) astUartData[i].pcRxOutDataPtr = &astUartData[i].acRxCircularBuffer[0]; //wrap pointer } astUartData[i].iNbRxFIFOPendingBytes -= iNbPendingData; switch(i) { // case DRIVE_UART_PORT: // { // //printf("drive rx\n"); // DriveProtocolRxData(aTempBuffer,iNbPendingData); // break; // } // case CU_UART_PORT: // { // CUProtocolRxData(aTempBuffer,iNbPendingData); // HCAM 20120918 // break; // } case NETWORK_UART_PORT: { //HEARTBEAT_LED_1_TOGGLE_REG = HEARTBEAT_LED_1_TOGGLE_MASK; //UartTransmitData(CONSOLE_UART_PORT, aTempBuffer, iNbPendingData);//echo received character int i = 0; for(i = 0; i< iNbPendingData; i++) { ProtocolAnalyzeNewData(aTempBuffer[i]); //RxTerminalData(aTempBuffer[i]); } break; } case LTE_IF_UART_PORT: { int i = 0; for(i = 0; i< iNbPendingData; i++) { // LTE_MODULE_RX_LED_PIN = ~LTE_MODULE_RX_LED_PIN; LTEModuleNewData(aTempBuffer[i]); //ProtocolAnalyzeNewData(aTempBuffer[i]); //RxTerminalData(aTempBuffer[i]); } break; } } } } return UART_OK; } //----------------------------------------------------------------------------- // // This function is used in the case of a large amount of data to be sent or received // in a process without going back to main loop. void UartBlockAndTick(unsigned int TickCount) { int i; // KickWatchdog(); for(i = 0; i < TickCount; i++) { UartTick(); } // KickWatchdog(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // This function is used in the case of a large amount of data to be sent or received // in a process without going back to main loop. int UartBlockUntillBufEmpty(int iUartHandle) { if(iUartHandle >= MAX_UART_HANDLE) return 0; // KickWatchdog(); while(astUartData[iUartHandle].iDataPending) { UartTick(); } // KickWatchdog(); return 1; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //Overload the stdio character output routine to redirect printfs // //void _mon_putc(char c) //{ // KickWatchdog(); // U2TXREG = c; // while (U2STAbits.TRMT==0); //#ifdef USE_BLOCKING_PRINTF // switch(CONSOLE_UART_PORT) // { // case UART_1: //(422) Uart 1B // { // if(U1MODEbits.ON == 1) // { // U1TXREG = c; // while (U1STAbits.TRMT==0); // } // break; // } // case UART_2: //(422) Uart 2A // { // if(U2MODEbits.ON == 1) // { // U2TXREG = c; // while (U2STAbits.TRMT==0); // } // break; // } // } //#else // UartTransmitData(PRINTF_UART_PORT, &c, 1); //#endif // UartTransmitData(CONSOLE_UART_PORT, &c, 1); // Nop(); // KickWatchdog(); //} /* void _mon_write (const char * s, unsigned int count) { #ifdef USE_BLOCKING_PRINTF int i; for(i = 0; i < count; i++) _mon_putc(*s++); #else UartTransmitData(UART_10, s, count); #endif }*/ //EOF