#define UART2_USE_AS_MODBUS

#include "main.h"  //although STM32CubeIDE has no counterpart of xc32.h ,  it has main.h which has uniform head file, no need each #ifdef to define uniform include file

#include "modbus.h"  
uint32_t getSysTickLOAD() {
	return SysTick->LOAD;
}
uint32_t getSysTickVAL() {
	return SysTick->VAL;
}

volatile bool Uart1TxDone=false;
volatile bool Uart2TxDone=false;
volatile bool Uart3TxDone=false;
volatile bool Uart4TxDone=false;

//We may use TxCpltCallBack but must modify them  because some Uart not for modbus (because all UARTs share the same callback). We must modify switch case which is not for Modbus RTU
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  {
#if defined(USART1)
    	if (huart->Instance == USART1)  Uart1TxDone=true;
#else
    	if (huart->Instance == UART1)  Uart1TxDone=true;
#endif
#if defined(USART2)
    	else if (huart->Instance == USART2)  Uart2TxDone=true;
#else
    	else if (huart->Instance == UART2)  Uart2TxDone=true;
#endif
#if defined(USART3)
    	else if (huart->Instance == USART3)  Uart3TxDone=true;
#else
    	else if (huart->Instance == UART3)  Uart3TxDone=true;
#endif
#if defined(USART4)
    	else if (huart->Instance == USART4)  Uart4TxDone=true;
#else
    	else if (huart->Instance == UART4)  Uart4TxDone=true;
#endif
    	//Add user code for non-Modbus ---start

    	//Add user code for non-Modbus ---end
 }




#ifdef UART1_USE_AS_MODBUS 
    //because defined in uart1.h
    volatile uint32_t tick4rxd1;    //Uart1 rxd tick  (Also used for txd)
    volatile uint32_t tmr4rxd1;    //Uart1 rxd timer1 value  (Also used for txd)
    extern UART_HandleTypeDef huart1;
    UART_HandleTypeDef * phuart1= &huart1;
    bool  UART1_TransmitDone(void)
    {
    	bool result;
    	result=Uart1TxDone;
    	//if (result)  Uart1TxDone=false;
    	return result;
    }

#else
    volatile uint32_t tick4rxd1;    //Uart1 rxd tick  (Also used for txd)
    volatile uint32_t tmr4rxd1;    //Uart1 rxd timer1 value  (Also used for txd)
    UART_HandleTypeDef * phuart1= (void *)0;
    bool  __attribute__ ((weak)) UART1_TransmitDone(void)
    {
    
    return true;
    }
#endif
#ifdef UART2_USE_AS_MODBUS    
    volatile uint32_t tick4rxd2;    //Uart2 rxd tick
    volatile uint32_t tmr4rxd2;    //Uart2 rxd timer1 value
    extern UART_HandleTypeDef huart2;
    UART_HandleTypeDef * phuart2= &huart2;
    bool  UART2_TransmitDone(void)
    {
    	bool result;
    	result=Uart2TxDone;
    	//if (result)  Uart2TxDone=false;
    	return result;
    }
#else
    volatile uint32_t tick4rxd2;    //Uart2 rxd tick
    volatile uint32_t tmr4rxd2;    //Uart2 rxd timer1 value
    UART_HandleTypeDef * phuart2= (void *)0;
    bool __attribute__ ((weak)) UART2_TransmitDone(void)
    {
        return true;
    }  
#endif
#ifdef UART3_USE_AS_MODBUS 
    volatile uint32_t tick4rxd3;    //Uart3 rxd tick
    volatile uint32_t tmr4rxd3;    //Uart3 rxd timer1 value
    extern UART_HandleTypeDef huart3;
    UART_HandleTypeDef * phuart3= &huart3;
    bool  UART3_TransmitDone(void)
    {
    	bool result;
    	result=Uart3TxDone;
    	//if (result)  Uart3TxDone=false;
    	return result;
    }
#else
    volatile uint32_t tick4rxd3;    //Uart3 rxd tick
    volatile uint32_t tmr4rxd3;    //Uart3 rxd timer1 value
    UART_HandleTypeDef * phuart3= (void *)0;
    bool __attribute__ ((weak)) UART3_TransmitDone(void)
    {
        return true;
    }   
#endif
#ifdef UART4_USE_AS_MODBUS 
    volatile uint32_t tick4rxd4;    //Uart4 rxd tick
    volatile uint32_t tmr4rxd4;    //Uart4 rxd timer1 value
    extern UART_HandleTypeDef huart4;
    UART_HandleTypeDef * phuart4= &huart4;
    bool  UART4_TransmitDone(void)
    {
    	bool result;
    	result=Uart4TxDone;
    	//if (result)  Uart4TxDone=false;
    	return result;
    }
#else
    volatile uint32_t tick4rxd4;    //Uart4 rxd tick
    volatile uint32_t tmr4rxd4;    //Uart4 rxd timer1 value
    UART_HandleTypeDef * phuart4= (void *)0;
    bool __attribute__ ((weak)) UART4_TransmitDone(void)
    {
        return true;
    } 
#endif

void myUART_Receive_IT(uint8_t UartNo, uint8_t *pData, uint16_t Size)
{
   switch(UartNo) {
   case 1:
	   HAL_UART_Receive_IT(phuart1, pData, Size);
	   break;
   case 2:
	   HAL_UART_Receive_IT(phuart2, pData, Size);
	   break;
   case 3:
	   HAL_UART_Receive_IT(phuart3, pData, Size);
	   break;
   default:
	   HAL_UART_Receive_IT(phuart4, pData, Size);
   }
}

#define MCU_UART_QTY 2

#include "modbus_User.h"
uint8_t my_MCU_UART_QTY=MCU_UART_QTY;

    


void __attribute__((weak)) EnableUART1_RS485Receive (uint8_t enable) // enable=1 => receive enable
{
    //Add your code
    // enable = 0 => TRANSMIT DATA, 0 = "output". enable = 1 => RECEIVE DATA, 1 = "input"
    if(enable==TX_DATA){                                      // Set the pin
          //LATBbits.LATB2=1;
          //LATCbits.LATC7=1;
          //TX1_Enable_SetHigh();
	}else{                                              //Clear the pin
          //LATBbits.LATB2=0;
        //LATCbits.LATC7=0;
         //TX1_Enable_SetLow();
	}
}
void __attribute__((weak)) EnableUART2_RS485Receive (uint8_t enable) 
{
    //Add your code
    // enable = 0 => TRANSMIT DATA, 0 = "output". enable = 1 => RECEIVE DATA, 1 = "input"
    if(enable==TX_DATA){                                      // Set the pin
          //LATBbits.LATB11=1;
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET);
        //TX2_Enable_SetHigh();
	}else{                                              //Clear the pin
          //LATBbits.LATB11=0;
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET);
        //TX2_Enable_SetLow();
	}
}
void __attribute__((weak)) EnableUART3_RS485Receive (uint8_t enable) 
{
    //Add your code
}
void __attribute__((weak)) EnableUART4_RS485Receive (uint8_t enable) 
{
    //Add your code
}

    
//only for decrease memory consumed , not for architecture difference  
#if MCU_UART_QTY==-1    //Simulink will craete MCU_UART_QTY=-1 when we don't use Uart
    uint8_t LinearBufferTx1[1]; 
    LinearBuf_type LinearTx1;  
    uint8_t LinearBufferTx2[1];
    LinearBuf_type LinearTx2;    
    uint8_t LinearBufferTx3[1];
    LinearBuf_type LinearTx3;  
    uint8_t LinearBufferTx4[1];
    LinearBuf_type LinearTx4;   

    uint8_t LinearBufferRx1[1];
    RingBuffer_t RingRx1;
    uint8_t LinearBufferRx2[1];
    RingBuffer_t RingRx2;
    uint8_t LinearBufferRx3[1];
    RingBuffer_t RingRx3;
    uint8_t LinearBufferRx4[1];
    RingBuffer_t RingRx4;


#endif
#if MCU_UART_QTY==1    
    #ifdef UART1_USE_AS_MODBUS
    uint8_t LinearBufferTx1[256]; 
    uint8_t LinearBufferRx1[256];


    #else
    uint8_t LinearBufferTx1[1]; 
    uint8_t LinearBufferRx1[1];


    #endif



    LinearBuf_type LinearTx1;  
    uint8_t LinearBufferTx2[1];
    LinearBuf_type LinearTx2;    
    uint8_t LinearBufferTx3[1];
    LinearBuf_type LinearTx3;  
    uint8_t LinearBufferTx4[1];
    LinearBuf_type LinearTx4;

    RingBuffer_t RingRx1;
    uint8_t LinearBufferRx2[1];
    RingBuffer_t RingRx2;
    uint8_t LinearBufferRx3[1];
    RingBuffer_t RingRx3;
    uint8_t LinearBufferRx4[1];
    RingBuffer_t RingRx4;
#endif
#if MCU_UART_QTY==2    
    #ifdef UART1_USE_AS_MODBUS
    uint8_t LinearBufferTx1[256]; 
    uint8_t LinearBufferRx1[256];



    #else
    uint8_t LinearBufferTx1[1];
    uint8_t LinearBufferRx1[1];


    #endif

    #ifdef UART2_USE_AS_MODBUS
    uint8_t LinearBufferTx2[256];
    uint8_t LinearBufferRx2[256];


    #else
    uint8_t LinearBufferTx2[1];
    uint8_t LinearBufferRx2[1];


    #endif



    LinearBuf_type LinearTx1;
    LinearBuf_type LinearTx2;  
    uint8_t LinearBufferTx3[1];
    LinearBuf_type LinearTx3; 
    uint8_t LinearBufferTx4[1];
    LinearBuf_type LinearTx4;  

    RingBuffer_t RingRx1;
    RingBuffer_t RingRx2;
    uint8_t LinearBufferRx3[1];
    RingBuffer_t RingRx3;
    uint8_t LinearBufferRx4[1];
    RingBuffer_t RingRx4;
#endif
#if MCU_UART_QTY==3    
    #ifdef UART1_USE_AS_MODBUS
    uint8_t LinearBufferTx1[256]; 
    uint8_t LinearBufferRx1[256];

    #else
    uint8_t LinearBufferTx1[1];
    uint8_t LinearBufferRx1[1];


    #endif

    #ifdef UART2_USE_AS_MODBUS
    uint8_t LinearBufferTx2[256];
    uint8_t LinearBufferRx2[256];

    #else
    uint8_t LinearBufferTx2[1];
    uint8_t LinearBufferRx2[1];

    #endif

    #ifdef UART3_USE_AS_MODBUS
    uint8_t LinearBufferTx3[256];
    uint8_t LinearBufferRx3[256];


    #else
    uint8_t LinearBufferTx3[1];
    uint8_t LinearBufferRx3[1];


    #endif


    LinearBuf_type LinearTx1;
    LinearBuf_type LinearTx2;
    LinearBuf_type LinearTx3;
    uint8_t LinearBufferTx4[1];
    LinearBuf_type LinearTx4;

    RingBuffer_t RingRx1;
    RingBuffer_t RingRx2;
    RingBuffer_t RingRx3;
    uint8_t LinearBufferRx4[1];
    RingBuffer_t RingRx4;
#endif
#if MCU_UART_QTY==4    
    #ifdef UART1_USE_AS_MODBUS
    uint8_t LinearBufferTx1[256]; 
    uint8_t LinearBufferRx1[256];


    #else
    uint8_t LinearBufferTx1[1];
    uint8_t LinearBufferRx1[1];


    #endif

    #ifdef UART2_USE_AS_MODBUS
    uint8_t LinearBufferTx2[256];
    uint8_t LinearBufferRx2[256];


    #else
    uint8_t LinearBufferTx2[1];
    uint8_t LinearBufferRx2[1];


    #endif

    #ifdef UART3_USE_AS_MODBUS
    uint8_t LinearBufferTx3[256];
    uint8_t LinearBufferRx3[256];


    #else
    uint8_t LinearBufferTx3[1];
    uint8_t LinearBufferRx3[1];


    #endif

    #ifdef UART4_USE_AS_MODBUS
    uint8_t LinearBufferTx4[256];
    uint8_t LinearBufferRx4[256];

    #else
    uint8_t LinearBufferTx4[1];
    uint8_t LinearBufferRx4[1];

    #endif

    LinearBuf_type LinearTx1;
    LinearBuf_type LinearTx2;
    LinearBuf_type LinearTx3;
    LinearBuf_type LinearTx4;

    RingBuffer_t RingRx1;
    RingBuffer_t RingRx2;
    RingBuffer_t RingRx3;
    RingBuffer_t RingRx4;
#endif   
bool  UART1_IsRxReady(void)
{
    #ifdef UART1_USE_AS_MODBUS
		return !(RingRx1.pnt_w == RingRx1.pnt_r);
    #endif
    return 0;
}
void  UART1_ClearAll(void)
{
    #ifdef UART1_USE_AS_MODBUS
	    HAL_UART_AbortReceive_IT(phuart1);
	    Ring_Buff_Clear(&RingRx1);
    #endif
}
void  UART1_User_WriteBuffer( uint8_t *buffer , uint16_t numbytes )
{
    #ifdef UART1_USE_AS_MODBUS
	    Uart1TxDone=false;
	    HAL_UART_Transmit_IT(phuart1, buffer, numbytes);
    #endif
}
uint8_t  UART1_ReadX( void)
{
    #ifdef UART1_USE_AS_MODBUS
	    return Ring_Buff_Read_Byte(&RingRx1);
    #endif
	    return 0;
}

bool UART2_IsRxReady(void)
{
    #ifdef UART2_USE_AS_MODBUS
	    return !(RingRx2.pnt_w == RingRx2.pnt_r);
    #endif
	return 0;
}
void  UART2_ClearAll(void)
{
    #ifdef UART2_USE_AS_MODBUS
	    HAL_UART_AbortReceive_IT(phuart2);
	    Ring_Buff_Clear(&RingRx2);
    #endif
}
void UART2_User_WriteBuffer( uint8_t *buffer , uint16_t numbytes )
{
    #ifdef UART2_USE_AS_MODBUS
	    Uart2TxDone=false;
	    HAL_UART_Transmit_IT(phuart2, buffer, numbytes);
    #endif
}
uint8_t UART2_ReadX( void)
{
    #ifdef UART2_USE_AS_MODBUS
	    return Ring_Buff_Read_Byte(&RingRx2);
    #endif
	    return 0;
}
    
bool UART3_IsRxReady(void)
{
    #ifdef UART3_USE_AS_MODBUS

        return !(RingRx3.pnt_w == RingRx3.pnt_r);

    #endif
    return 0;
}
void UART3_ClearAll(void)
{
    #ifdef UART3_USE_AS_MODBUS
	    HAL_UART_AbortReceive_IT(phuart3);
	    Ring_Buff_Clear(&Ring3);
    #endif
}
void UART3_User_WriteBuffer( uint8_t *buffer , uint16_t numbytes )
{
    #ifdef UART3_USE_AS_MODBUS
	    Uart3TxDone=false;
	    HAL_UART_Transmit_IT(phuart3, buffer, numbytes);
    #endif
}
uint8_t UART3_ReadX( void)
{
    #ifdef UART3_USE_AS_MODBUS
        return Ring_Buff_Read_Byte(&RingRx3);
    #endif
        return 0;
}

bool UART4_IsRxReady(void)
{
    #ifdef UART4_USE_AS_MODBUS
        return !(RingRx4.pnt_w == RingRx4.pnt_r);
    #endif
    return 0;
}
void  UART4_ClearAll(void){
   #ifdef UART4_USE_AS_MODBUS
	    HAL_UART_AbortReceive_IT(phuart4);
	    Ring_Buff_Clear(&Ring4);
    #endif
}
void UART4_User_WriteBuffer( uint8_t *buffer , uint16_t numbytes )
{
    #ifdef UART4_USE_AS_MODBUS
	    Uart4TxDone=false;
	    HAL_UART_Transmit_IT(phuart4, buffer, numbytes);
    #endif
}
uint8_t  UART4_ReadX( void)
{
    #ifdef UART4_USE_AS_MODBUS
        return Ring_Buff_Read_Byte(&RingRx4);
    #endif
        return 0;
}

//We may use RxCpltCallBack but must modify them  because some Uart not for modbus (because all UARTs share the same callback). We must modify switch case which is not for Modbus RTU
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
#ifdef UART1_USE_AS_MODBUS
#ifdef USART1
      if (huart->Instance == USART1) {
#else
    	  if (huart->Instance == UART1) {
#endif
    		  //comment out condition, otherwise, never receiving when large data make full
    		  //if (!Ring_Buff_IsFull(&RingRx1))
    		  {
    			  HAL_UART_Receive_IT(huart, RingRx1.data, 256);  //Must be 255, cannot be 256 because ring buffer  =>256
    		  }
    	  }
#endif
#ifdef UART2_USE_AS_MODBUS
#ifdef USART2
    	  if (huart->Instance == USART2) {
#else
    		  if (huart->Instance == UART2) {
#endif
    			  //comment out condition, otherwise, never receiving when large data make full
    			  //if (!Ring_Buff_IsFull(&RingRx2))
    			  {  //data has put into already, only modify tail
    				  HAL_UART_Receive_IT(huart, RingRx2.data, 256);  //Must be 255, cannot be 256 because ring buffer=> 256 Because  we must make RingRx2.data[255] not empty. it must have data
    			  }
    		  }
#endif
#ifdef UART3_USE_AS_MODBUS
#ifdef USART3
    	  if (huart->Instance == USART3) {
#else
    		  if (huart->Instance == UART3) {
#endif
    			  //comment out condition, otherwise, never receiving when large data make full
    			  //if (!Ring_Buff_IsFull(&RingRx3))
    			  {  //data has put into already, only modify tail
    				  HAL_UART_Receive_IT(huart, RingRx3.data, 256);  //Must be 255, cannot be 256 because ring buffer
    			  }
    		  }
#endif
#ifdef UART4_USE_AS_MODBUS
#ifdef USART4
    	  if (huart->Instance == USART4) {
#else
    		  if (huart->Instance == UART4) {
#endif
    			  //comment out condition, otherwise, never receiving when large data make full
    			  //if (!Ring_Buff_IsFull(&RingRx4))
    			  {  //data has put into already, only modify tail
    				  HAL_UART_Receive_IT(huart, RingRx4.data, 256);  //Must be 255, cannot be 256 because ring buffer
    			  }
    		  }
#endif

//Add user code for non-Modbus ---start

//Add user code for non-Modbus ---end
}





































































































































































































































































































































































































































































