2 Replies Latest reply on May 3, 2020 9:54 PM by MoTa_728816

    tty_utils a utility sample for CLI type program

    MoTa_728816

      As a seasoned *nix hacker, I still can't live without command line interface (CLI) type program(s).

       

      After posting a response to such a question today, I realized that I may post this here, too.

      Re: I want the program won't run until I type in a character into UART.

       

      Although I still miss scanf(), printf(), I have learned that blocking type functions are not suitable for an embedded program.

      And after writing a few dozens of sample programs, I noticed that I have written same function(s) again and again.

      (Well, getting older may force you to repeat things...)

       

      Namely for my type of sample programs, I wrote many

      get_string() (or get_line()) /* fill str[] up to receiving delimiter or the buffer is full */

      prompt() /* show a prompt "> " */

      splash(char *program_name) /* print the name (and time) of the program, so that I can identify what it was */

      print(char *str) ; /* to hide difference between UART_UartPutString() and UART_PutString() ... */

       

      So I decided to make them my library so that I can save some time (but same time, lose warming up time)

       

      schematic (PSoC 4)

      001-schematic.JPG

      schematic (PSoC 5LP)

      003-5lp-schematic.JPG

       

      tty_utils.h

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

      #ifndef _TTY_UTILS_H_

      #define _TTY_UTILS_H_

      #include "project.h"

       

      void tty_init(void) ;

       

      void print(char *str) ;

       

      /**

      * get_string()

      * check if we received any char via tty

      * and store the char into str[]

      * when a delimiter is detected

      * it puts NULL at the current end of str[] and return the length of str

      * if the length is exceeding that STR_BUF_LEN,

      * it puts NULL at the end of str[] and returns -1

      */

      int get_string(void) ;

       

      /**

      * get_line()

      * similar with get_string() but only accept CR or LF for delimiter

      * so you can get a line up to the STR_BUF_LEN

      */

      int get_line(void) ;

       

      void splash(char *prog_name) ;

       

      void prompt(void) ;

       

      extern char str[] ; /* print buf */

       

      #endif /* _TTY_UTILS_H_ */

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

       

      tty_utils.c (PSoC 4 (CY8CKIT-044))

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

      #include "project.h"

      #include "stdio.h"

      #include "tty_utils.h"

       

      #define TAB   '\t'

      #define SPACE ' '

      #define CR    '\r'

      #define LF    '\n'

       

      #define RX_BUF_LEN  128

      #define STR_BUF_LEN  64

       

      volatile char rx_buf[RX_BUF_LEN] ;

      volatile int  rx_write_index = 0 ;

      int           rx_read_index  = 0 ;

      int           str_buf_index  = 0 ;

      char          str[STR_BUF_LEN + 1] ;

       

      static inline int is_delimiter(char c)

      {

          return((c == TAB)||(c == SPACE)||(c == CR)||(c == LF)) ;

      }

       

      static inline int is_eol(char c)

      {

          return((c == CR) || (c == LF)) ;

      }

       

      void print(char *str)

      {

          UART_UartPutString(str) ; /* for PSoC 4 */

      }

       

      CY_ISR(tty_rx_isr)

      {

          if (UART_SpiUartGetRxBufferSize()) {

              rx_buf[rx_write_index] = UART_UartGetByte() ;

              rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

          }

          UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY) ;

      }

       

      void splash(char *prog_name)

      {

          if (prog_name && *prog_name) {

              print(prog_name) ;

          }

          print(" (") ;

          print(__DATE__) ;

          print(" ") ;

          print(__TIME__) ;

          print(")\n") ;

      }

       

      void prompt(void)

      {

          print("> ") ;

      }

       

      void tty_init(void)

      {

          tty_rx_int_ClearPending() ;

          UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY) ;

          tty_rx_int_StartEx(tty_rx_isr) ;

          UART_Start() ;

      }

       

      int get_string(void)

      {

          int result = 0 ;

         

          if (rx_read_index != rx_write_index) {

              if (is_delimiter(rx_buf[rx_read_index])) {

                  str[str_buf_index] = (char)NULL ;

                  result = str_buf_index ;

                  str_buf_index = 0 ;

              } else {

                  str[str_buf_index++] = rx_buf[rx_read_index] ;

                  if (str_buf_index >= STR_BUF_LEN) {

                      str[STR_BUF_LEN] = (char)NULL ;

                      str_buf_index = 0 ;

                      result = -1 ; /* str buf overflow */

                  }

              }

              rx_read_index = (rx_read_index + 1) % RX_BUF_LEN ;

          }

          return( result ) ;

      }

       

      int get_line(void)

      {

          int result = 0 ;

         

          if (rx_read_index != rx_write_index) {

              if (is_eol(rx_buf[rx_read_index])) {

                  str[str_buf_index] = (char)NULL ;

                  result = str_buf_index ;

                  str_buf_index = 0 ;

              } else {

                  str[str_buf_index++] = rx_buf[rx_read_index] ;

                  if (str_buf_index >= STR_BUF_LEN) {

                      str[STR_BUF_LEN] = (char)NULL ;

                      str_buf_index = 0 ;

                      result = -1 ; /* str buf overflow */

                  }

              }

              rx_read_index = (rx_read_index + 1) % RX_BUF_LEN ;

          }

          return( result ) ;

      }

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

       

      tty_utils.c (PSoC 5LP (CY8CKIT-059))

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

      #include "project.h"

      #include "stdio.h"

      #include "tty_utils.h"

       

      #define TAB   '\t'

      #define SPACE ' '

      #define CR    '\r'

      #define LF    '\n'

       

      #define RX_BUF_LEN  128

      #define STR_BUF_LEN  64

       

      volatile char rx_buf[RX_BUF_LEN] ;

      volatile int  rx_write_index = 0 ;

      int           rx_read_index  = 0 ;

      int           str_buf_index  = 0 ;

      char          str[STR_BUF_LEN + 1] ;

       

      static inline int is_delimiter(char c)

      {

          return((c == TAB)||(c == SPACE)||(c == CR)||(c == LF)) ;

      }

       

      static inline int is_eol(char c)

      {

          return((c == CR) || (c == LF)) ;

      }

       

      void print(char *str)

      {

          UART_PutString(str) ; /* for PSoC 5LP */

      }

       

      CY_ISR(tty_rx_isr)

      {

          if (UART_GetRxBufferSize()) {

              rx_buf[rx_write_index] = UART_GetByte() ;

              rx_write_index = (rx_write_index + 1) % RX_BUF_LEN ;

          }

          tty_rx_int_ClearPending() ;

      }

       

      void splash(char *prog_name)

      {

          if (prog_name && *prog_name) {

              print(prog_name) ;

          }

          print(" (") ;

          print(__DATE__) ;

          print(" ") ;

          print(__TIME__) ;

          print(")\n") ;

      }

       

      void prompt(void)

      {

          print("> ") ;

      }

       

      void tty_init(void)

      {

          tty_rx_int_ClearPending() ;

          tty_rx_int_StartEx(tty_rx_isr) ;

          UART_Start() ;

      }

       

      int get_string(void)

      {

          int result = 0 ;

         

          if (rx_read_index != rx_write_index) {

              if (is_delimiter(rx_buf[rx_read_index])) {

                  str[str_buf_index] = (char)NULL ;

                  result = str_buf_index ;

                  str_buf_index = 0 ;

              } else {

                  str[str_buf_index++] = rx_buf[rx_read_index] ;

                  if (str_buf_index >= STR_BUF_LEN) {

                      str[STR_BUF_LEN] = (char)NULL ;

                      str_buf_index = 0 ;

                      result = -1 ; /* str buf overflow */

                  }

              }

              rx_read_index = (rx_read_index + 1) % RX_BUF_LEN ;

          }

          return( result ) ;

      }

       

      int get_line(void)

      {

          int result = 0 ;

         

          if (rx_read_index != rx_write_index) {

              if (is_eol(rx_buf[rx_read_index])) {

                  str[str_buf_index] = (char)NULL ;

                  result = str_buf_index ;

                  str_buf_index = 0 ;

              } else {

                  str[str_buf_index++] = rx_buf[rx_read_index] ;

                  if (str_buf_index >= STR_BUF_LEN) {

                      str[STR_BUF_LEN] = (char)NULL ;

                      str_buf_index = 0 ;

                      result = -1 ; /* str buf overflow */

                  }

              }

              rx_read_index = (rx_read_index + 1) % RX_BUF_LEN ;

          }

          return( result ) ;

      }

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

       

      main.c as a sample program

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

      #include "project.h"

      #include "stdio.h"

      #include "tty_utils.h"

       

      void init_hardware(void)

      {

          tty_init() ;

          CyGlobalIntEnable; /* Enable global interrupts. */

      }

       

      int main(void)

      {

          init_hardware() ;

       

          splash("tty utils test") ;

       

          prompt() ;

          for(;;) {

      //        if (get_string() > 0) { // got a string

              if (get_line()) { // got a line

                  print("Got: ") ;

                  print(str) ;

                  print("\n") ;

                  prompt() ;

              }

          }

      }

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

       

      moto