.. _uart2_dynamic_pin_switching:

UART2 Dynamic Pin Switching
===========================
The UART2 TX and RX pins can be reassigned during runtime. This can enable the |DEVICE|
to interface with multiple UART streams connected to different TX/RX pins during
runtime.

UART2 TX/RX Pin Switching Functionality
---------------------------------------
The run-time UART2 pin reconfiguration can be implemented using the ``UART2switchPins()``
function displayed below:

.. code-block:: c
   
   static void UART2switchPins(uint8_t oldTxPin, uint8_t oldRxPin, uint8_t newTxPin, uint8_t newRxPin, uint8_t newTxMux, uint8_t newRxMux)
   {
      //Settings old UART pins to internal MUX
      GPIO_setConfigAndMux(oldTxPin, GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, GPIO_MUX_GPIO);
      GPIO_setConfigAndMux(oldRxPin, GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, GPIO_MUX_GPIO);

      // Configuring new UART pins for UART
      GPIO_setConfigAndMux(newTxPin, GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, newTxMux);
      GPIO_setConfigAndMux(newRxPin, GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, newRxMux);

      return;
   }

The ``UART2switchPins()`` function  takes in the currently used UART pins, the new UART pins along 
with the new MUX, and reconfigures them such that the new pins are now used for UART transmissions.

Before the function is called, the UART RX/TX buffers should be cleared, this can be done by closing
and re-opening the UART2 handle.

UART2 Dynamic Pin Switching Example
-----------------------------------

The UART2 Dynamic Pin Switching functionality has been added to the uart2echo example and the
application code can be found in this section. In this example, the UART pins change whenever
either of the LaunchPad buttons are pressed.

.. code-block:: c

   #include <stdint.h>
   #include <stddef.h>
   #include <ti/drivers/GPIO.h>
   #include <ti/drivers/UART2.h>
   #include "ti_drivers_config.h"


   UART2_Handle uart;
   uint8_t xdsUARTStatus = 0;
   uint8_t altUARTStatus = 0;



   static void UART2switchPins(uint8_t oldTxPin, uint8_t oldRxPin, uint8_t newTxPin, uint8_t newRxPin, uint8_t newTxMux, uint8_t newRxMux)
   {
      //Settings old UART pins to internal MUX
      GPIO_setConfigAndMux(oldTxPin, GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, GPIO_MUX_GPIO);
      GPIO_setConfigAndMux(oldRxPin, GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, GPIO_MUX_GPIO);

      // Configuring new UART pins for UART
      GPIO_setConfigAndMux(newTxPin, GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, newTxMux);
      GPIO_setConfigAndMux(newRxPin, GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, newRxMux);

      return;
   }


   /*
   *  ======== mainThread ========
   */
   void *mainThread(void *arg0)
   {
      const char   switchingAltMsg[] = "\r\nSwitching UART to DIO13 & DIO12:\r\n";
      const char   switchingXDSMsg[] = "\r\nSwitching UART to DIO20 & DIO22:\r\n";
      const char   echoPrompt[] = "Echoing characters:\r\n";
      char         input;
      UART2_Params uartParams;
      size_t       bytesRead;
      size_t       bytesWritten = 0;
      uint32_t     status = UART2_STATUS_SUCCESS;


      /* Call driver init functions */
      GPIO_init();
      /* Configure the LED and button pins */
      GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
      GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

      /* Turn on user LED */
      GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);

      /* Create a UART where the default read and write mode is BLOCKING */
      UART2_Params_init(&uartParams);
      uartParams.baudRate = 115200;
      uartParams.readMode = UART2_Mode_NONBLOCKING;

      uart = UART2_open(CONFIG_UART2_0, &uartParams);

      if (uart == NULL) {
         /* UART2_open() failed */
         while (1);
      }

      // XDS UART pins are being used
      xdsUARTStatus = 1;

      /* Turn on user LED to indicate successful initialization */
      GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
      UART2_write(uart, echoPrompt, sizeof(echoPrompt), &bytesWritten);

      /* Loop forever echoing */
      while (1) {
         bytesRead = 0;
         while (bytesRead == 0  && GPIO_read(CONFIG_GPIO_BUTTON_0) != 0 && GPIO_read(CONFIG_GPIO_BUTTON_1) != 0) {
               status = UART2_read(uart, &input, 1, &bytesRead);

               if (status != UART2_STATUS_SUCCESS && status !=UART2_STATUS_EAGAIN) {
                  /* UART2_read() failed */
                  while (1);
               }
         }

         bytesWritten = 0;
         while (bytesWritten == 0 && GPIO_read(CONFIG_GPIO_BUTTON_0) != 0 && GPIO_read(CONFIG_GPIO_BUTTON_1) != 0) {
               status = UART2_write(uart, &input, 1, &bytesWritten);

               if (status != UART2_STATUS_SUCCESS) {
                  /* UART2_write() failed */
                  while (1);
               }
         }

         // Reconfigure UART to use XDS uart (DIO20 and DIO22)
         if(GPIO_read(CONFIG_GPIO_BUTTON_0) == 0)
         {
               // Clear other UART
               altUARTStatus = 0;

               // If we are not in this UART config
               if(xdsUARTStatus != 1)
               {
                  // Close and restart UART to clear buffers
                  UART2_close(uart);
                  UART2_open(CONFIG_UART2_0, &uartParams);

                  // Perform the switch
                  UART2switchPins(13, 12, 20, 22, 2, 2);  // Old TX/RX ((13,12) New TX/RX (20,22) New MUX TX/RX (2,2)

                  // Set the current UART
                  xdsUARTStatus = 1;

                  // Print switch message
                  UART2_write(uart, &switchingXDSMsg, sizeof(switchingXDSMsg), &bytesWritten);
                  UART2_flushRx(uart);
               }
         }

         // Reconfigure UART to use alternative UART (DIO13 and DIO12)
         if(GPIO_read(CONFIG_GPIO_BUTTON_1) == 0)
         {
               // Clear other UART
               xdsUARTStatus = 0;

               // If we are not in this UART config
               if(altUARTStatus != 1)
               {
                  // Close and restart UART to clear buffers
                  UART2_close(uart);
                  UART2_open(CONFIG_UART2_0, &uartParams);

                  // Perform the switch
                  UART2switchPins(20, 22, 13, 12, 3, 3);  // Old TX/RX (20,22) New TX/RX (13,12) New MUX TX/RX (3,3)

                  // Set the current UART
                  altUARTStatus = 1;

                  // Print switch message
                  UART2_write(uart, &switchingAltMsg, sizeof(switchingAltMsg), &bytesWritten);
                  UART2_flushRx(uart);
               }
         }
         // Reset input buffer
         input = 0;
      }

      return NULL;
   }

