tty_utils a utility sample for CLI type program

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

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

0 Likes
2 Replies
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

A minor update

(1) cls() function added

(2) STR_BUF_LEN was moved from tty_utils.c to tty_utils.h

     so that in the main body of the program we can do

      snprintf(str, STR_BUF_LEN, "%d %s\n", ivalue, char_ptr) ;

(3) In the beginning of splash()  cls() function was added.

moto

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Last night while I was debugging my MCU Tester

I was frustrated as it did not accept "Backspace"

MCU Tester, a Swiss Army Knife for PSoC (CY8CKIT-044 version)

For a very long time (years), I've been using my Tera Term with Local Echo (ON).

But recently while I was porting the TinyBasic, I came across with a Backspace process.

And with the CardKb, Backspace was working fine.

Tiny Basic for PSoC (CY8CKIT-044 / TSoC / CY8CKIT-059 / CY8CKIT-062-BLE)

Then why can't I do it with tty? ... It should be done if I turn off Local Echo.

So here it is, now  "Backspace" works... sorry I must be slow.

moto

0 Likes