4 Replies Latest reply on Mar 1, 2019 1:09 AM by hida_4040201

    Realtime GPIO Connection

    hida_4040201

      Hey,

       

      I am new with PSOC so please bare with me. I tried to find an answer by myself but so far I am not able to. I come from embedded C and ARM Cortex-M background with extensive experience.

       

      I was exploring PSOC for a new project, what I want to do is to control the route of some digital signals. The board will have 2 connectors, and I want to route signals from one connector to the other based on user's configuration. The user will connect signals to some GPIO pins, using PSOC I want to re-route these signals to other GPIO pins. Prior to user configuration I do not know which Pin will be connected to which and whether the signal is input or output. To rephrase, there is a data bus connected to some pins; using the PSOC I want to reroute these signals to other pins. The problem is I cannot make this decision while using the PSOC creator, it needs to be done in the field.

       

      Example:

      In the field the user will decide to connect J1.1 to J2.3, later he will decide to connect J1.1 to J2.4 etc... The user can be asked to select if the signal is input or output in the field.

       

      1. Is it possible to control the hardware blocks using the C code instead of the PSOC creator schematic ? e.g connect P0[3] to P0[5] using C instead of schematic design
      2. Is there a way to implement the above using control registers and other blocks?

       

      I tried to use back to back mux with bidirectional pins but at build time I get the below errors.

       

       

      Thank you for any help

        • 1. Re: Realtime GPIO Connection
          MoTa_728816

          Hi,

           

          This was a fun problem to challenge, following is the result of my half day trial.

          Although basically it seems to be working, I have NOT fully tested nor confirmed so please proceed with caution.

          Meantime, because of the nature of application, we could easily destroy the device,

          so in case you connect something to the pin please use  appropriate resistor(s) to protect the device.

           

          I only tested the case J1.1 is input and J2.1 is output, and it seemed to be working.

           

          schematic

          003-Schematic.JPG

          main.c

          =======================

          #include "project.h"

          #include <stdio.h>

           

          #define TAB '\t'

          #define SPACE ' '

          #define CR '\r'

          #define LF '\n'

           

          #define STR_LEN 128

          char str[STR_LEN+1] ; /* print buffer */

          volatile char rx_buf[STR_LEN+1] ; /* buffer for UART_RX */

          volatile int rx_index = 0 ;

          volatile int str_received = 0 ;

           

          int is_delimiter(uint8_t c)

          {

              int result = 0 ;

              switch(c) {

              case TAB:

              case SPACE:

              case CR:

              case LF:

                  result = 1 ;

                  break ;

              }

              return( result ) ;

          }

           

          CY_ISR(uart_rx_isr)

          {

              uint8_t c ;

           

          //    UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY) ; /* for PSoC 4 */

              if (UART_GetRxBufferSize()) {

                  c = UART_GetByte() ;

                  if ((rx_index >= STR_LEN) || is_delimiter(c)) {

                      rx_buf[rx_index] = (char)0 ;

                      str_received = 1 ;

                      rx_index = 0 ;

                  } else {

                      rx_buf[rx_index++] = c ;

                  }

              }

          }

           

          void print(char *str)

          {

              UART_PutString(str) ;

          }

           

          void init_hardware(void)

          {

              CyGlobalIntEnable; /* Enable global interrupts. */   

              UART_Start() ;

              isr_uart_rx_StartEx(uart_rx_isr) ;

          }

           

          void get_string(char *str)

          {

              uint8_t int_flag ;

             

              while(1) {

                  if (str_received) {

                      int_flag = CyEnterCriticalSection() ;

                      strcpy(str, (char *)rx_buf) ;

                      str_received = 0 ;

                      CyExitCriticalSection(int_flag) ;

                      break ;

                  }

              }

          }

           

          void help(void)

          {

              print("=== commands ===\n") ;

              print("reset     : reset and clear all connections\n") ;

              print("list      : list current connections\n") ;

              print("Jx.x Jy.y : connect input Jy.y to output Jx.x\n") ;

              print("            Example  J1.1 J2.1 (J1.1 <= J2.1)\n") ;

              print("=================\n") ;

          }

           

          void splash(void)

          {

              sprintf(str, "IO MUX Test (%s %s)\n\r", __DATE__, __TIME__) ;

              print(str) ;

              help() ;

          }

           

          void prompt(void)

          {

              print("> ") ;

          }

           

          void do_reset(void)

          {

              OE_Write(0x00) ; /* stop all output enables */

              J1_IN_Write(0x00) ;

              J2_IN_Write(0x00) ;

          }

           

          int get_con_pin(char *name, int *con, int *pin)

          {

              int result = 0 ;

              switch(name[1]) {

              case '1': *con = 1 ; break ;

              case '2': *con = 2 ; break ;

              default:

                  sprintf(str, "Invalid Connector Name [ %s ]\n", name) ;

                  print(str) ;

                  result++ ;

                  break ;

              }

              switch(name[3]) {

              case '1': *pin = 1 ; break ;

              case '2': *pin = 2 ; break ;

              case '3': *pin = 3 ; break ;

              case '4': *pin = 4 ; break ;

              default:

                  sprintf(str, "Invalid Connector Name [ %s ]\n", name) ;

                  print(str) ;

                  result++ ;

                  break ;

              }

              return( result ) ;

          }

           

          void list_regs(void)

          {

              int i, dst_con, dst_pin, src_con, src_pin ;

              uint8_t oe_value, sel1_value, sel2_value ;

              oe_value = OE_Read() ;

              sprintf(str, "OE: 0x%02X ", oe_value ) ;

              print(str) ;

              sel1_value = J1_IN_Read() ;

              sprintf(str, "J1: 0x%02X ", sel1_value ) ;

              print(str) ;

              sel2_value = J2_IN_Read() ;

              sprintf(str, "J2: 0x%02X\n", sel2_value) ;

              print(str) ;  

              for (i = 0 ; i < 8 ; i++ ) {

                  if (oe_value & (0x01 << i)) {

                      dst_con = (i / 4) + 1 ;

                      dst_pin = (i % 4) + 1 ;

                      if (dst_con == 1) {

                          src_con = 2 ;

                          src_pin = ((sel1_value >> ((dst_pin - 1) * 2)) & 0x03) + 1 ;

                      } else {

                          src_con = 1 ;

                          src_pin = ((sel2_value >> ((dst_pin - 1) * 2)) & 0x03) + 1 ;

                      }

                      sprintf(str, "J%d.%d <= J%d.%d\n", dst_con, dst_pin, src_con, src_pin ) ;

                      print(str) ;

                  }

              }           

          }

           

          int connect_wire(int dst_con, int dst_pin, int src_con, int src_pin)

          {

              uint8_t oe_value, sel_value ;

              uint8_t bit ;

              int result = 0 ;

             

              if (dst_con == src_con) {

                  print("Can not connect same connectors\n") ;

                  result = 1 ;

              }

             

              // select input for destination IN_SEL

              bit = 2 * (dst_pin - 1) ; /* lsb for sel */

              if (dst_con == 1) {

                  sel_value = J1_IN_Read() ;

                  sel_value &= ~(0x03 << bit) ; /* clear 2bit for sel */

                  sel_value |= ((src_pin - 1) & 0x03) << bit ;

                  J1_IN_Write(sel_value) ;

              } else if (dst_con == 2) {

                  sel_value = J2_IN_Read() ;

                  sel_value &= ~(0x03 << bit) ; /* clear 2bit for sel */

                  sel_value |= ((src_pin - 1) & 0x03) << bit ;

                  J2_IN_Write(sel_value) ;

              }

             

              // set source to be input

              oe_value = OE_Read() ;

              bit = 4 * (src_con - 1) + (src_pin - 1) ;

              oe_value &= ~(0x01 << bit) ; /* clear OE for the source pin */

              // set destintion to be output

              bit = 4 * (dst_con - 1) + (dst_pin -1) ;

              oe_value |= (0x01 << bit) ; /* set OE for the destination pin */

              OE_Write(oe_value) ;

             

              return( result ) ;

          }

           

           

          void do_command(char *command)

          {

              char source[32] ;

              int src_con, src_pin, dst_con, dst_pin ;

             

              if (strcmp(command, "reset") == 0) {

                  print("Connection Reset!\n") ;

                  do_reset() ;

              } else if (strcmp(command, "list") == 0) {

                  list_regs() ;

              } else if ((*command == 'j')||(*command == 'J')) { /* J1.1 etc */

                  if (get_con_pin(command, &dst_con, &dst_pin) == 0) {

                      get_string(source) ;

                      if (get_con_pin(source, &src_con, &src_pin) == 0) {

                          connect_wire(dst_con, dst_pin, src_con, src_pin) ;

                          sprintf(str, "J%d.%d <= J%d.%d\n", dst_con, dst_pin, src_con, src_pin) ;

                          print(str) ;

                      }

                  }

              } else {

                  help() ;

              }

          }

           

          int main(void)

          {

              char command[32] ;

             

              init_hardware() ;

             

              splash() ;

             

              for(;;) {

                  prompt() ;

                  get_string(command) ;

                  do_command(command) ;

              }

          }

          =======================

           

          TeraTerm log

          002-TeraTerm-log.JPG

           

          moto

          • 2. Re: Realtime GPIO Connection
            LinglingG_46
            1. Is it possible to control the hardware blocks using the C code instead of the PSOC creator schematic ? e.g connect P0[3] to P0[5] using C instead of schematic design

                

                  Yes, it is Ok to use the C code to control hardware block, you can control all hardware part by register.

                  The easy way to understand it is that when you configure the pins by creator schematic, then compile it, check the generate codes.

                  You can write the codes which the IDE does.

             

             

            1. Is there a way to implement the above using control registers and other blocks?

               If you don't use the M1 and S1 connected to y, use other pins which don't been used by the Multiplexer, then it will no error. As error report explains that we don't support internal three -state signals.

             

            I tried to use back to back mux with bidirectional pins but at build time I get the below error.

             

            Please don't use the M1 and S1 as the Tri-state buffer y-inout.

            • 3. Re: Realtime GPIO Connection
              hida_4040201

              Oh woow thanks a lot for this extensive answer motac_1799631, I really appreciate it

              • 4. Re: Realtime GPIO Connection
                hida_4040201
                1. Is it possible to control the hardware blocks using the C code instead of the PSOC creator schematic ? e.g connect P0[3] to P0[5] using C instead of schematic design

                   

                      Yes, it is Ok to use the C code to control hardware block, you can control all hardware part by register.

                      The easy way to understand it is that when you configure the pins by creator schematic, then compile it, check the generate codes.

                      You can write the codes which the IDE does.

                 

                Is there any documentation on this ? I couldn't find any. Also when I check the generated code (for the pins for example) it only shows the API that I can use (set, clear ...) it doesn't show the hardware connection code. Can you point me to the C file that contains the hardware connections ?